zoukankan      html  css  js  c++  java
  • 结构模式--之--代理模式

    代理模式是对象的结构模式,代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。
    按照使用目的来划分,代理有以下几种:
    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 }
  • 相关阅读:
    MVC+jQuery开发B/S系统②:表单绑定
    插入排序
    笔记:实例管理
    文件读写冲突的解决办法:ReaderWriterLock
    MVC+jQuery数据绑定①:列表绑定(二)
    MVC+jQuery数据绑定①:列表绑定(三)
    非递归求 T(n) = [T(n1),n,T(n1)] 已知T1=[1]
    笔记:契约总结
    面试题:1~ n1 有n个数,是有序的,找出重复的那个数。
    Thread系列——ThreadPool
  • 原文地址:https://www.cnblogs.com/wn398/p/3230244.html
Copyright © 2011-2022 走看看