代理模式,一言以蔽之,为其他的对象提供一种代理以控制对这个对象的访问,for example,买火车票的时候可以在代售处购买,起到了一个中介的作用,但是我们可以在这里买票也可以电话购票,但是却只能去火车站退票,故代理可去掉功能服务或增加额外的服务
一.基本原理
1.远程代理:为不同地理空间的对象提供局域网代表对象,比如远程监控各个分店的销售情况
2.虚拟代理:根据将资源消耗很大的对象进行延迟,真正需要的时候再创建,比如说当我们浏览新闻时,图片加载很慢,但是可以显示一个虚拟的图片,待真实图片加载完成后再进行显示。
3.保护代理:控制对一个对象的访问权限,比如说在网站上的操作,普通用户只有浏览的权限,注册用户可以发帖等
4.智能引用代理:提供对目标对象额外的一些服务,类似于刚才提到的火车票代售处,提供了额外的电话预约服务
二.代码实现
智能引用代理:两种实现方式,静态代理和动态代理,首先需要了解一下这两个概念:
静态代理:代理和被代理对象在代理之前是确定的,它们都实现相同的接口或继承相同的类
public interface Movable { void move(); }
public class Car implements Movable { @Override public void move() { //实现开车 try { Thread.sleep(new Random().nextInt(1000)); System.out.println("汽车行驶中"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
//通过继承实现代理,car2对car的代理,并且在方法前后增加了自己的业务逻辑 public class Car2 extends Car { @Override public void move() { long start = System.currentTimeMillis(); System.out.println("汽车开始行驶"); super.move(); long end = System.currentTimeMillis(); System.out.println("汽车行驶时间是"+(end-start)+"毫秒"); } }
//通过聚合的方式实现代理 public class Car3 implements Movable { private Car car; public Car3(Car car) { super(); this.car = car; } @Override public void move() { long start = System.currentTimeMillis(); System.out.println("汽车开始行驶"); car.move(); long end = System.currentTimeMillis(); System.out.println("汽车行驶时间是"+(end-start)+"毫秒"); } }
package com.proxy; //测试类 public class Client { public static void main(String[] args) { Movable car2 = new Car2(); car2.move(); Car car = new Car(); Movable car3 = new Car3(car); car3.move(); } }
以上列出了两种代理实现的方式,分别是继承实现代理和聚合实现代理,究竟哪种更加合适一些呢?比如说,我们需要建立一个代理通过继承的方式,在代理类中增加以下功能:
1.日志记录 2.时间记录 3.限制权限 我们可以通过继承car实现
现在又需要建立一个代理,实现以下功能
1.权限 2.时间 3.日志 还可以通过继承car实现。。。。但很明显通过继承的方式实现代理功能的叠加会导致代理类无限膨胀下去,显然,继承不太适合代理。那聚合方式如何呢?
//通过聚合的方式实现代理 public class CarLogProxy implements Movable { private Movable m; public CarLogProxy(Movable m) { super(); this.m = m; } @Override public void move() { long start = System.currentTimeMillis(); System.out.println("汽车开始行驶"); m.move(); long end = System.currentTimeMillis(); System.out.println("汽车行驶时间是"+(end-start)+"毫秒"); } }
//通过聚合的方式实现代理 public class CarTimeProxy implements Movable { private Movable m; public CarTimeProxy(Movable m) { super(); this.m = m; } @Override public void move() { System.out.println("日志开始"); m.move(); System.out.println("日志结束"); } }
//测试类 public class Client { public static void main(String[] args) { // Movable car2 = new Car2(); // car2.move(); // Car car = new Car(); // Movable car3 = new Car3(car); // car3.move(); Car car = new Car(); CarLogProxy clp = new CarLogProxy(car); CarTimeProxy ctp = new CarTimeProxy(clp); ctp.move(); } }
显然,这种方式可以方便的实现代理。那么,如果我现在又需要一个火车代理记录时间,是否也需要重新建立代理类呢?那么能否动态产生代理,实现对不同类的代理呢?