Java设计模式之--代理模式学习
1.代理模式定义
为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介服务,可以去掉功能服务和增加额外的服务。
其实按照官方的说法可能不太好理解,代理模式就好比我们生活中买票,一般情况下我们都会去火车站(原对象)买票,但是有的情况下可能我们离火车站比较远不方便去,那我们就会去火车票代售点去(我们的代理对象)买,在这里代售处就是对火车站的一个代理,可以实现卖票的功能,同时呢,代售处也有自己的额外的功能,比如火车票代售处买票需要额外的手续费,火车站能提供的所有服务代售处不是全有,比如代售处不能退票、不能购买学生票,从这里可以看出代理实现了原对象的部分功能外,也有自己额外的处理。
2.代理模式实现--静态代理
静态代理:代理和被代理的对象在代理之前都是确定的,他们都是实现了相同的接口或者继承了相同的抽象类。
举例说明下:汽车有一个move()方法,然后我想通过代理来实现记录汽车运行过程中时间的问题。
Moveable.java //定义一个统一的接口,里面定义了一个汽车行驶move()方法
- public interface Moveable {
- void move();
- }
Car.java(版本一) //实现了Moveable接口,实现move方法
- public class Car implements Moveable {
- public void move() {
- try {
- Thread.sleep(new Random().nextInt(1000));
- System.out.println("汽车行驶中....");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
在这里要实现增加记录汽车运行时间问题,我们是不是可以直接修改Car.java的move方法,如下所示:
- public class Car implements Moveable {
- public void move() {
- System.out.println("汽车行驶开始");
- long begin = System.currentTimeMillis();
- try {
- Thread.sleep(new Random().nextInt(1000));
- System.out.println("汽车行驶中....");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- long end = System.currentTimeMillis();
- System.out.println("汽车行驶了"+(end-begin)+"毫秒");
- }
- }
这样就实现了记录行驶时间,但是这个得修改Car.java源码,在不修改源码的情况下,怎么做呢,我们就可以通过代理来实现,这里我们将Car.java还原为版本一时候
Car2.java //新增Car2,继承了Car
- public class Car2 extends Car {
- public void move() {
- System.out.println("汽车行驶开始");
- long begin = System.currentTimeMillis();
- super.move();
- long end = System.currentTimeMillis();
- System.out.println("汽车行驶了"+(end-begin)+"毫秒");
- }
- }
Client.java //测试类,
- public class Client {
- public static void main(String[] args) {
- // Car car = new Car();
- // car.move();
- Moveable m = new Car2();
- m.move();
- }
- }
可以看到运行结果:
- 汽车行驶开始
- 汽车行驶中....
- 汽车行驶了314毫秒
这样就通过代理实现了记录时间的问题。在super.move();之前和之后我们可以添加新的服务。
上面我们是通过的继承的方式来实现代理,下面我们换一种方式,用聚合的方式来实现代理模式。
Car3.java //新增Car3.java ,采用聚合方式实现
- public class Car3 implements Moveable {
- private Car car;
- public Car3(Car car){
- this.car = car;
- }
- public void move() {
- System.out.println("汽车行驶开始");
- long begin = System.currentTimeMillis();
- car.move();
- long end = System.currentTimeMillis();
- System.out.println("汽车行驶了"+(end-begin)+"毫秒");
- }
- }
修改Client.java来测试,
- public class Client {
- public static void main(String[] args) {
- //采用聚合方式测试代码
- Car car = new Car();
- Car3 car3 = new Car3(car);
- car3.move();
- }
- }
通过运行我们可以得到相同的结果,都可以实现相同的功能。
但是哪一种方式更好呢,这里我们仅仅是需要增加个记录时间的功能,假如我们需要增加功能有1.时间记录2.日志记录3.权限控制等,可能有的汽车需要先记录时间在记录日志在是权限,即是123方式,可能有的汽车需要321方式,有的汽车只需要1等等,如果我们采用继承的方式的话,每一种方式我们会创建一个新的Java类,这样的话我们的类会无限的庞大,所以推荐使用聚合方式来实现,那聚合方式怎么实现呢,且看下文。
CarTimeProxy.java //时间代理类,完成对记录时间的代理功能
- public class CarTimeProxy implements Moveable {
- private Moveable m;
- public CarTimeProxy(Moveable m){
- this.m = m;
- }
- public void move() {
- System.out.println("汽车行驶开始");
- long begin = System.currentTimeMillis();
- m.move();
- long end = System.currentTimeMillis();
- System.out.println("汽车行驶了"+(end-begin)+"毫秒");
- }
- }
CarLogProxy.java //日志代理类,完成对日志的记录
- public class CarLogProxy implements Moveable {
- private Moveable m;
- public CarLogProxy(Moveable m){
- this.m = m;
- }
- public void move() {
- System.out.println("汽车日志记录开始");
- m.move();
- System.out.println("汽车日志记录结束");
- }
- }
修改Client.java来测试,假如我们先记录日志在记录时间
- public class Client {
- public static void main(String[] args) {
- Car car = new Car();
- CarTimeProxy time = new CarTimeProxy(car);
- CarLogProxy log = new CarLogProxy(time);
- log.move();
- }
- }
结果可以看出,先是记录了日志在是时间
- 汽车日志记录开始
- 汽车行驶开始
- 汽车行驶中....
- 汽车行驶了586毫秒
- 汽车日志记录结束
这里假如我们需要先记录时间在记录日志,我们仅仅是代码顺序切换下就OK了,
- public class Client {
- public static void main(String[] args) {
- Car car = new Car();
- CarLogProxy log = new CarLogProxy(car);
- CarTimeProxy time = new CarTimeProxy(log);
- time.move();
- }
- }
- 汽车行驶开始
- 汽车日志记录开始
- 汽车行驶中....
- 汽车日志记录结束
- 汽车行驶了192毫秒
从这里可以看出,聚合的方式比继承更适合代理模式
Java设计模式之--代理模式学习的更多相关文章
- Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景
我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...
- java设计模式6——代理模式
java设计模式6--代理模式 1.代理模式介绍: 1.1.为什么要学习代理模式?因为这就是Spring Aop的底层!(SpringAop 和 SpringMvc) 1.2.代理模式的分类: 静态代 ...
- 夜话JAVA设计模式之代理模式(Proxy)
代理模式定义:为另一个对象提供一个替身或者占位符以控制对这个对象的访问.---<Head First 设计模式> 代理模式换句话说就是给某一个对象创建一个代理对象,由这个代理对象控制对原对 ...
- Java设计模式:代理模式(转)
代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.这里使用到编程中的一 ...
- JAVA设计模式:代理模式&& 装饰模式区别
在前面学习了代理模式和装饰模式后,发现对两者之间有时候会混淆,因此对两者进行了区别和理解: 装饰模式你可以这样理解,就像糖一样,卖的时候商家大多要在外面包一层糖纸,其实原本还是糖. public in ...
- Java设计模式之代理模式(Proxy)
前言: 最近在研究Retrofit开源框架的时候,其主要核心代码是通过注解标示参数,动态代理模式实现具体接口,反射机制进行参数解析,最终实现发送请求.其实之前在学习Xutils源码的时候,Xutils ...
- Java 设计模式_代理模式(2016-08-19)
概念: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 就是一个人或者机构代表另一个人或者机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一 ...
- Java设计模式:代理模式(二)
承接上文 三.计数代理 计数代理的应用场景是:当客户程序需要在调用服务提供者对象的方法之前或之后执行日志或者计数等额外功能时,就可以用到技术代理模式.计数代理模式并不是把额外操作的代码直接添加到原服务 ...
- java设计模式之代理模式 ,以及和java 回调机制的区别
java 代理模式就是: 将自己要做的事交给别人去做(这个别人就是代理者,自己就是被代理者),为什么自己能做的要交给别人去做了?假如一个小学生小明,现在要写作业,但是又想玩游戏,他更想玩游戏,并且不想 ...
随机推荐
- Linux下的线程
一.线程的优点 与传统进程相比,用线程来实现相同的功能有如下优点: (1)系统资源消耗低. (2)速度快. (3)线程间的数据共享比进程间容易的多. 二.多线程编程简单实例 #include < ...
- 修改FFMpeg源码—捕获丢包
概述 最近我们项目有一个需求就是解决客户端播放RTSP视频流花屏的问题,一般来说丢包就会引起花屏,导致客户端花屏的因素又有很多,比如说: 相机到服务器丢包 服务器到客户端丢包 等等... 其中服务器到 ...
- 使用 satis 搭建一个私有的 Composer 包仓库
在我们的日常php开发中可能需要使用大量的composer包,大部份都可以直接使用,但在公司内部总有一小部份包是不能公开的,这时候我们就需要搭建一个公司内部使用的composer仓库,好在compos ...
- MR中的combiner和partitioner
1.combiner combiner是MR编程模型中的一个组件: 有些任务中map可能会产生大量的本地输出,combiner的作用就是在map端对输出先做一次合并,以减少map和reduce节点之间 ...
- docker 中运行 sshd 服务
创建Dockerfile # sshd # # VERSION 0.0.2 FROM ubuntu:14.04 MAINTAINER admln <admln@docker.com> RU ...
- mongodb 操作语句与sql操作语句对比
上行:SQL 操作语句 下行:Mongo 操作语句 CREATE TABLE USERS (a Number, b Number) db.createCollection("mycoll&q ...
- uva 216 Getting in Line 最短路,全排列暴力做法
题目给出离散的点,要求求出一笔把所有点都连上的最短路径. 最多才8个点,果断用暴力求. 用next_permutation举出全排列,计算出路程,记录最短路径. 这题也可以用dfs回溯暴力,但是用最小 ...
- asp.net oracle 存储过程
ORACLE代码 CREATE OR REPLACE PROCEDURE gd_CURSOR(MYCS1 OUT SYS_REFCURSOR,MYCS2 OUT SYS_REFCURSOR,a out ...
- apache2.4 +django1.9+python3+ubuntu15.10
这是我这几天学习部署django的总结,中间出现了不少的问题.特此记录下来,用来复习巩固,同时也希望给想学习的同学一些参考. 第一步:我在ubuntu上装的是python3.sudo apt-get ...
- js 数组中随机出来N组
var word = []; while (word.length < 7) { var tmp = data[parseInt(Math.random() * data.length)]; v ...