设计模式_代理模式(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();}}



0 0
原创粉丝点击