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设计模式之--代理模式学习的更多相关文章

  1. Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景

    我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...

  2. java设计模式6——代理模式

    java设计模式6--代理模式 1.代理模式介绍: 1.1.为什么要学习代理模式?因为这就是Spring Aop的底层!(SpringAop 和 SpringMvc) 1.2.代理模式的分类: 静态代 ...

  3. 夜话JAVA设计模式之代理模式(Proxy)

    代理模式定义:为另一个对象提供一个替身或者占位符以控制对这个对象的访问.---<Head First 设计模式> 代理模式换句话说就是给某一个对象创建一个代理对象,由这个代理对象控制对原对 ...

  4. Java设计模式:代理模式(转)

    代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.这里使用到编程中的一 ...

  5. JAVA设计模式:代理模式&& 装饰模式区别

    在前面学习了代理模式和装饰模式后,发现对两者之间有时候会混淆,因此对两者进行了区别和理解: 装饰模式你可以这样理解,就像糖一样,卖的时候商家大多要在外面包一层糖纸,其实原本还是糖. public in ...

  6. Java设计模式之代理模式(Proxy)

    前言: 最近在研究Retrofit开源框架的时候,其主要核心代码是通过注解标示参数,动态代理模式实现具体接口,反射机制进行参数解析,最终实现发送请求.其实之前在学习Xutils源码的时候,Xutils ...

  7. Java 设计模式_代理模式(2016-08-19)

    概念: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 就是一个人或者机构代表另一个人或者机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一 ...

  8. Java设计模式:代理模式(二)

    承接上文 三.计数代理 计数代理的应用场景是:当客户程序需要在调用服务提供者对象的方法之前或之后执行日志或者计数等额外功能时,就可以用到技术代理模式.计数代理模式并不是把额外操作的代码直接添加到原服务 ...

  9. java设计模式之代理模式 ,以及和java 回调机制的区别

    java 代理模式就是: 将自己要做的事交给别人去做(这个别人就是代理者,自己就是被代理者),为什么自己能做的要交给别人去做了?假如一个小学生小明,现在要写作业,但是又想玩游戏,他更想玩游戏,并且不想 ...

随机推荐

  1. mysql 升级方法

    Performing an In-place Upgrade This section describes how to perform an in-place upgrade. Review Bef ...

  2. Java核心技术卷二部分笔记

    第1章 流与文件 1.2 文本输入与输出 第3章 网络 3.3 可中断套接字 第4章 数据库编程 4.5.2 读写LOB 4.6 可滚动和可更新的结果集 4.8 元数据 第6章 高级Swing 6.1 ...

  3. 非常详细的 Docker 学习笔记

    一.Docker 简介 Docker 两个主要部件: Docker: 开源的容器虚拟化平台 Docker Hub: 用于分享.管理 Docker 容器的 Docker SaaS 平台 -- Docke ...

  4. Is an MTD device a block device or a char device?

    转:http://www.linux-mtd.infradead.org/faq/general.html#L_mtd_what Note, you can find Ukranian transla ...

  5. 9. Android框架和工具之 SlidingMenu(抽屉菜单)

    详见为知笔记:Android / Android用户界面优化 / Android SlidingMenu菜单栏程序设计

  6. [Android]天气App 3 网络数据的请求和Json解析

      Android客户端开发,不仅仅是在Android端开发,还需要有相应的后台服务支持,否则的话,客户端的数据就只能放到本地自己做处理.我认为的原生态的App就是对应服务端的Client.他能像浏览 ...

  7. 查询SQL SERVER数据库日志工具

    在SQL SERVER中查看操作日志,一直是一个比较麻烦的事情,因为微软并没有提供直接的系统工具可以查看日志内容,虽然可以通过非正式的隐藏接口dbcc log 获取日志的非解析编码但是要还原是个非常麻 ...

  8. LearnMVC5-GettingStarted

    原创文章,转载必需注明出:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/learnmvc5-gettingstarted/ 本人是 ...

  9. CentOS安装VMware Tools

    新建cdrom挂载目录 mkdir /mnt/cdrom 挂载光驱 mount -t auto /dev/cdrom /mnt/cdrom这命令就是把CentOS CDROM挂载在/mnt/cdrom ...

  10. hdu 3062 2-SAT问题

    思路:裸的2-SAT. #include<map> #include<set> #include<cmath> #include<queue> #inc ...