结构模式--之--代理模式

代理模式是对象的结构模式,代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。
按照使用目的来划分,代理有以下几种:
1.远程(Remote)代理:为一个位于不同的地址空间的对象提供一个局域代表对象。优点 是系统可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。客户完全可以认为被代理的对象是局域的,而不是远程的而代理对象承担了大部分的网络通信工作。缺点是客户可能没有意识到会启动一个耗费时间的远程调用,因此客户没有必要的思想准备。
2.虚拟(Virtual)代理:根据需要创建一个资源消耗较大的对象,使得此对象只在需要时才会被真正创建。代理可以对加载的过程加以必要的优化。当一个模块的加载十分耗费资源的时候,虚拟代理的优点就非常明显。
3.Copy-on-Write代理:虚拟代理的一种。把复制(克隆)拖延到只有在客户端需要时,才真正采取行动。
4.保护(Protect or Access)代理:控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限
5.Cache代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
6.防火墙(Firewall)代理:保护目标,不让恶意用户接近
7.同步化(Synchronization)代理:使几个用户能够同时使用一个对象而没有冲突。
8.智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等。
  在所有种类的代理模式中,虚拟代理,远程代理,智能引用代理和保持代理是最为常见的代理模式。
 
代理模式的角色有:
1.抽象主题角色:声明了真实主题和代理主题的共同接口,这样一来在任何可以使用真实主题的地方都可以使用代理主题。
2.代理主题(Proxy)角色:代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象,代理主题角色提供一个与真实主题角色相同的接口,以便可以在任何时候都可以替代真实主体,控制对真实主题的引用,负责在需要的时候创建真实主题对象(和删除真实主题对象),代理角色通常在将客户端调用传递给真实的主题之前或之后,都要执行某个操作,而不是单纯地将调用传递给真实主题对象。
3.真实主题角色:定义了代理角色所代表的真实对象。
示例性代码如下:
 1 public class ProxyTest {
 2     public static void main(String[] args) {
 3         Subject subject = new ProxySubject();
 4         subject.request();
 5     }
 6 }
 7 
 8 
 9 //抽象主题角色
10 abstract class Subject{
11     //抽象请求方法
12     abstract public void request();
13 }
14 
15 //具体角色
16 class RealSubject extends Subject{
17     //实现真实的请求方法
18     @Override
19     public void request() {
20         System.out.println("From real subject");
21     }
22     
23 }
24 
25 //代理角色,它除了将所有的请求原封不动地委派给真实主题角色外,还在委派前和后执行了一些操作
26 class ProxySubject extends Subject{
27     
28     private RealSubject realSubject;
29     
30     //请求方法
31     @Override
32     public void request() {
33         preRequest();
34         if(null == realSubject){
35             realSubject = new RealSubject();
36         }
37         realSubject.request();
38         postRequest();
39     }
40     //请求前
41     public void preRequest(){
42         System.out.println("Before Request");
43     }
44     //请求后
45     public void postRequest(){
46         System.out.println("After Request");
47     }
48 }

 

从JDK3后,Java语言通过在java.lang.reflect库中提供下面三个类直接支持代理模式:Proxy,InvocationHandler和Method.其中Proxy类使得设计师能够在运行时间创建代理对象,当系统有了一个代理对象后,对原对象的方法调用会首先被分派给一个调用处理处理器(InvocationHandler).程序可以在调用处理器invoke()方法中截获这个调用,进行额外的操作。显然Java所提供的这一支持是建立在反射之上的。
设计师可以按以下步骤创建动态代理对象
1.指明一系列的接口来创建一个代理对象
2.创建一个调用处理器(InvocationHandler)对象
3.将这个代理指定为某个其他对象的代理对象
4.在调用处理器的invoke()方法中采取代理,一方面将调用传递给真实对象,另一方面执行各种需要做的操作。
 
 
 
以下以一个例子来说明使用动态代理:为一个Vector对象提供一个代理对象,当Vector的任何方法被调用之前和调用之后,分别打印出两条信息,这表明代理对象能能力截获和控制这个Vector对像
 1 public class DynamicProxy {
 2     public static void main(String[] args) throws Exception{
 3         
 4         List list= (List)VectorProxy.factory(new Vector());        
 5         list.add("one");
 6         list.add("two");
 7         
 8     }
 9 }
10 
11 class VectorProxy implements InvocationHandler{
12     
13     private Object proxyobj;
14     
15     public VectorProxy(Object obj){
16         this.proxyobj = obj;
17     }
18     
19     //调用某个方法
20     @Override
21     public Object invoke(Object proxy, Method method, Object[] args)
22             throws Throwable {
23         System.out.println("Before calling"+method);
24         Object o = method.invoke(proxyobj, args);
25         System.out.println("After calling"+method);
26         return o;
27     }
28     public static Object factory(Object obj) throws Exception{
29         Class cls = obj.getClass();
30         return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),new VectorProxy(obj));
31         
32     }
33 }

 

posted @ 2013-08-01 15:53  丁丁木木  阅读(230)  评论(0编辑  收藏  举报