设计模式_代理模式(Proxy)
来源:互联网 发布:淘宝客没有pid 编辑:程序博客网 时间:2024/05/22 11:44
代理模式(Proxy)
代理模式是使用频率非常高的模式,定义是为其他对象提供一种代理以控制对这个对象的访问(provide a surrogate or placeholder for another object to contro access to it )。
1. 基本类图
定义一个ICar的接口,然后定义一个具体的实现类Car。增加一个驾驶员的代理类。这样的话就是说想启动汽车得通过驾驶员。由驾驶员驾驶汽车。
代码也比较简单。
定义一个接口,里面有一个run方法。
public interface ICar {public void run();}
定义一个具体的实现类,实现接口里面的run方法
public class Car implements ICar {@Overridepublic void run() {System.out.println("汽车启动了,速度很快");}}
定义一个驾驶员类。实现run方法。这里注意:代理类所做的工作不是实现“实现类”里面的具体操作而是代理实现,什么时候可以做,什么时候不可以做。
假如:需要限制一个类的访问、限制一个资源的访问。
public class CarDriver implements ICar {private ICar car;public CarDriver(ICar _car) {this.car = _car;}public void run() {Random rand = new Random();if(rand.nextBoolean()){System.out.println("驾驶员同意启动汽车");car.run();}else{System.out.println("驾驶员不同意启动汽车");}}}
调用类。这个没什么好说的。
public class Client {public static void main(String args[]){ICar car = new Car();ICar carAgent = new CarDriver(car);carAgent.run();}}
2. 强制代理
上面的基本类图是可以直接调用Car的。汽车没有驾驶员就直接可以自己跑了。这是不科学的,所以就有了这么一种强制代理。
强制代理比较另类,一般的都是通过代理类去找真是角色,就像我通过驾驶员去找汽车。而强制代理就比较特别了。得通过汽车去找驾驶员,你想上车先去找老司机,你不找到老司机我就不给你上车。不管你是new一个老司机,还是通过代理类都不行。这车只认开它的那个老司机。
意思就是说高层模块new了一个真实角色对象,但是返回的确是代理类的对象。
就像你想上一辆车,但是你得刷卡,卡在老司机那。所以你得先找到车,老司机在车上啊,然后就找到老司机,老司机给你卡,你上车。
这么一个访问控制可能有有点绕。绝对的访问控制,你不能通过别的任何方式调用真实角色,只能通过代理类来访问控制。类图可能与上面的没有什么区别,有一些区别我也没画上去。看代码就一切了然了。
这个是接口与一般模式没什么区别,新增了一个获取老司机的方法。
public interface ICar {public void run();public ICar getCarDriver();}
真实角色类,这里区别就来了。新增了一个getCar()的方法这个方法主要的作用是返回一个代理类,就是这个车的老司机。而下面还有一个isProxy()方法。这个方法是判断有没有代理。到底这个老司机在不在车上呢。
public class Car implements ICar {private ICar car = null;@Overridepublic void run() {if(this.isProxy())System.out.println("汽车启动了,速度很快");elseSystem.out.println("请通过代理访问");}@Overridepublic ICar getCarDriver() {this.car = new CarDriver(this);return this.car;}private boolean isProxy(){if(this.car == null)return false;elsereturn true;}}
代理类,这就与普通代理有区别了。这个构造方法,返回一个真实角色类。下面有一个是没有代理直接返回自己。返回null也一样。
public class CarDriver implements ICar {public ICar car;public CarDriver(ICar _car){this.car = _car;}@Overridepublic void run() {Random rand = new Random();if(rand.nextBoolean()){System.out.println("驾驶员同意启动汽车");car.run();}else{System.out.println("驾驶员不同意启动汽车");}}public ICar getCarDriver() {return this;}}
这里是调用类,上面的代码看的一头雾水。看这个调用类就能一目了然了,原来不过如此。
public class Client {public static void main(String args[]){ICar car = new Car();car.run();//ICar carDriver = new CarDriver(car);ICar carDriver = car.getCarDriver();carDriver.run();}}
3. 动态代理(压轴大戏)
动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。就像你先上车,上车再刷卡一样。不用找老司机了,上车你自然就看到了。动态代理是根据被代理的接口生成所有的方法。默认情况下所有的方法返回值都是空。现在AOP就是用动态代理,有兴趣可以研究下。如果有时间下一篇可以说说。
这个实现InvocationHandler接口的类的作用就是产生一个动态代理对象。InvocationHandler接口是JDK提供动态代理的接口,对被代理类的方法进行代理。
invoke方法是必须要实现的。他完成对真实方法的调用。即所有被代理的方法都由InvocationHandler接管。具体可以去看API。附上一篇感觉还不错的InvocationHandler详解
public class CarDriverIH implements InvocationHandler {//被代理的实例Object obj = null;public CarDriverIH(Object _obj){this.obj = _obj;}@Overridepublic Object invoke(Object arg0, Method method, Object[] arg2) throws Throwable {Object result = method.invoke(this.obj, arg2);return result;}}这个是被代理类的接口。
public interface ICar {public void runCar();}
被代理类,真实角色类。
public class Car implements ICar {@Overridepublic void runCar() {System.out.println("汽车启动了,速度很快");}}
这个就是客户端类。我们没有创建代理类,也没有实现ICar的接口。但是就实现了上面一般代理类的功能。这就是动态代理。
public class Client {public static void main(String args[]){ICar car = new Car();InvocationHandler handler = new CarDriverIH(car);ClassLoader cl = car.getClass().getClassLoader();//ICar carProxy = (ICar) Proxy.newProxyInstance(cl, car.getClass().getInterfaces(), handler);ICar carProxy = (ICar) Proxy.newProxyInstance(cl, new Class[]{ICar.class}, handler);carProxy.runCar();}}
- 设计模式_代理模式(Proxy)
- Proxy代理设计模式
- 设计模式 - 代理(Proxy)
- 代理设计模式--Proxy
- Proxy(代理)设计模式
- 代理 proxy 设计模式
- 设计模式系列之三_代理模式(Proxy)
- 设计模式----Proxy(代理)模式
- 设计模式--代理模式(Proxy)
- 设计模式 -- 代理模式(Proxy)
- 设计模式--代理模式(Proxy)
- [设计模式]Proxy代理模式
- 设计模式--Proxy(代理模式)
- [设计模式]代理模式(Proxy)
- 设计模式-Proxy代理模式
- 设计模式--proxy代理模式
- 设计模式 -- 代理模式 Proxy
- 设计模式-代理模式(Proxy)
- nls_charset_name(n1)
- 为什么Activity生命周期函数是运行在UI线程
- Android屏幕适配
- 二叉树中相距最远的两个节点之间的距离
- UVA - 110 Meta-Loopless Sorts
- 设计模式_代理模式(Proxy)
- nls_charset_id(c1)
- HEXTORAW(c1)
- Android-理解Context
- BMP文件格式
- scala进阶18-隐式对象
- CONVERT(c1,set1,set2)
- MP4 seek状态 sample读取流程
- seajs 2.x _ seajs是什么 & 源代码片段