常见设计模式之Proxy篇

来源:互联网 发布:汇丰杯sas数据分析 编辑:程序博客网 时间:2024/06/13 09:25

根据Design Pattern描述,常用Proxy设计模式分为四种:virtual proxy, remote proxy,protection proxy和smart reference,相应的句子如下:

1. A remote proxy provides a local representative for an object in a different address space

2. A virtual proxy creates expensive objects on demand.

3. A protection proxy controls access to the original object. Protection proxies are useful when objects should have different access rights.

4.A smart reference is a replacement for a bare pointer that performs a additional actions when an object is accessed. Typical uses include

   ① counting the number of reference to the real object so that it can be freed automatically when there are no more references(also called smart pointer)

   ② loading a persistent object into memory when it's first referenced

   ③ checking that the real object is locked before it's accessed to ensure that no other object can change it.

remote proxy 保存为一个远端对象的引用,当Client需要相应的方法时,会把访问的参数传递给本地的一个proxy对象,然后本地的proxy对象将参数进行编码转发给远端的实际对象。virtual proxy往往用于延迟初始化,对于一些对象的构建比较复杂和消耗空间和性能时,我们往往会使用延迟初始化这样的技术。通过这种代理模式,能将复杂对象的初始化给封装好,而客户端直接与代理进行交互,当实际要使用相应的方法时,才进行实例化具体对象并转发相应的方法给具体的对象。也就是说,对于客户端来讲,Proxy和Real Object直接并无区别。一般来说,当实际初始化Real Object后,Proxy会保存其一个引用。

下面就写一个protection proxy的静态代理和动态代理的例子。

package net.liuyx.test;public class ProxyTest {public static void main(String[] args){Bureau iface = (Bureau) new Secretary();iface.sign();iface.eat();}}//某局interface Bureau{void sign();void eat();}//请局长吃饭和签字要经过秘书这一关class Secretary implements Bureau{private final Head head;Secretary(){head = new Head();}public void sign(){head.sign();}public void eat(){head.eat();}private static class Head implements Bureau{public void sign(){System.out.println("header sign!");} public void eat(){System.out.println("ask the head to eat successly");};}}
其输出为

很显然,局长这个类被秘书给保护起来了,转发给局长的方法都会经过秘书这个代理。下面写一个关于动态代理的实现。动态代理会多一个InvocationHandler类的实现,该类用来为代理转发具体的参数:

package net.liuyx.test;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class ProxyTest {public static void main(String[] args) {Bureau head = (Bureau) new Head();Bureau secretary = (Bureau) Proxy.newProxyInstance(Bureau.class.getClassLoader(), new Class[] { Bureau.class },new DefaultHandler(head));//动态产生代理,在第二个Demo中,并没有为Secretary写代码,Proxy的这个静态方法会动态产生一个代理,该方法需要穿几个参数:ClassLoad对象,被代理对象实现的接口列表(记住,是接口列表,不包含抽象类),和一个InvocationHandler对象doSomething(secretary);}public static void doSomething(Bureau b){b.eat();b.sign();}}// 某局interface Bureau {void sign();void eat();}class Head implements Bureau {@Overridepublic void sign() {System.out.println("header sign!");}@Overridepublic void eat() {System.out.println("ask the head to eat successly");}}class DefaultHandler implements InvocationHandler {Object proxied;DefaultHandler(Object proxied) {this.proxied = proxied;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {System.out.println("proxy handler the request to the real object");System.out.println("It's method is: " + method.getName()+ " and is params is " + args);return method.invoke(proxied, args);//InvocationHandler的精髓就在这个方法里了,通过反射调用实际被代理对象的方法,并传进参数}}

输出:


其他几种代理模式的编写方法也类似,在此就不赘述了。只不过在Virtual Proxy模式中,在具体操作被代理对象时才实例化对象,比如调用eat 和sign时才实例化该对象,而不是在构造器中实例化。

其实Protection proxy代理模式有点像Decorator模式,但装饰器模式往往是给一个对象动态添加一个或多个职责,两者的出发点不一样。而protected的出发点是为了控制实际对象的访问。