代理设计模式

1.  简介

代理模式(Proxy Pattern)是GoF 23种Java常用设计模式之一。代理模式的定义:Provide a surrogate or placeholder for another object to controlaccess to it(为其他对象提供一种代理以控制对这个对象的访问)。使用代理模式创建代理对象,让代理对象控制目标对象的访问(目标对象可以是远程的对象、创建开销大的对象或需要安全控制的对象),并且可以在不改变目标对象的情况下添加一些额外的功能

2.  UML类图



3.  模式中包含的角色及其职责

Subject:抽象主题角色,抽象主题类可以是抽象类,也可以是接口,是一个最普通的业务类型定义,无特殊要求。

RealSubject:具体主题角色,也叫被委托角色、被代理角色。是业务逻辑的具体执行者。

Proxy:代理主题角色,也叫委托类、代理类。它把所有抽象主题类定义的方法给具体主题角色实现,并且在具体主题角色处理完毕前后做预处理和善后工作。(最简单的比如打印日志)

4.  代码实现

(1)    Subject

package com.jackie.designpatterns.proxy;

/**

 抽象主题,定义主要功能

 */

publicinterface Subject {

   publicvoid operate();

}

(2)    RealSubject

package com.jackie.designpatterns.proxy;

/**

 具体主题

 */

publicclass RealSubject implements Subject{

 

   @Override

   publicvoid operate() {

        System.out.println("realsubject operatestarted......");

   }

}

(3)     Proxy

package com.jackie.designpatterns.proxy;

/**

 代理类

 */

publicclass Proxy implements Subject{

 

   private Subject subject;

 

   public Proxy(Subject subject) {

        this.subject = subject;

   }

 

   @Override

   publicvoid operate() {

        System.out.println("before operate......");

        subject.operate();

        System.out.println("after operate......");

   }

}

(4)     Client

package com.jackie.designpatterns.proxy;

/**

 客户

 */

publicclass Client {

   /**

    @param args

    */

   publicstaticvoid main(String[] args) {

        Subject subject = new RealSubject();

        Proxy proxy = new Proxy(subject);

        proxy.operate();

   }

}

运行结果:     beforeoperate......

realsubject operate started......

afteroperate......

5.   应用场景

现实世界中,秘书就相当于一个代理,老板开会,那么通知员工开会时间、布置会场、会后整理会场等等开会相关工作就可以交给秘书做,老板就只需要开会就行了,不需要亲自做那些事。同理,在我们程序设计中也可使用代理模式来将由一系列无关逻辑组合在一起的代码进行解耦合,比如业务代码中的日志代码就可以在代理中进行。Spring的AOP就是典型的动态代理应用。

6.   代理模式的应用形式

(1)远程代理(Remote Proxy) -可以隐藏一个对象存在于不同地址空间的事实。也使得客户端可以访问在远程机器上的对象,远程机器可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。

(2)虚拟代理(Virtual Proxy) – 允许内存开销较大的对象在需要的时候创建。只有我们真正需要这个对象的时候才创建。

(3)写入时复制代理(Copy-On-Write Proxy) – 用来控制对象的复制,方法是延迟对象的复制,直到客户真的需要为止。是虚拟代理的一个变体。

(4)保护代理(Protection (Access)Proxy) – 为不同的客户提供不同级别的目标对象访问权限

(5)缓存代理(Cache Proxy) – 为开销大的运算结果提供暂时存储,它允许多个客户共享结果,以减少计算或网络延迟。

(6)防火墙代理(Firewall Proxy) – 控制网络资源的访问,保护主题免于恶意客户的侵害。

(7)同步代理(SynchronizationProxy) – 在多线程的情况下为主题提供安全的访问。

(8)智能引用代理(Smart ReferenceProxy) - 当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等。

(9)复杂隐藏代理(Complexity HidingProxy) – 用来隐藏一个类的复杂集合的复杂度,并进行访问控制。有时候也称为外观代理(Façade Proxy),这不难理解。复杂隐藏代理和外观模式是不一样的,因为代理控制访问,而外观模式是不一样的,因为代理控制访问,而外观模式只提供另一组接口。

7,应用场景举例:

 

比如西门庆找潘金莲,那潘金莲不好意思答复呀,咋办,找那个王婆做代理,表现在程序上时是这样的体现的

先说说这个场景中的要素:一种类型的女人,潘金莲,王婆,西门庆,后来扩展的贾氏也和西门庆勾上了,我们是假设的,然后西门庆找潘金莲happy,但潘金莲不好意思直接,就找个王婆代理呗。我们看看具体代码。

 

先定义一种女人

Java代码   收藏代码
  1. package com.yangguangfu.proxy;  
  2. /** 
  3.  *  
  4.  * @author 阿福([email protected])
     
  5.  *定义一种类型的女人,王婆和潘金莲都属于这个类型的女人 
  6.  */  
  7. public interface KindWoman {  
  8.       
  9.     //这种女人能做什么事情呢?  
  10.     public void makeEyesWithMan();//抛媚眼  
  11.       
  12.     public void happyWithMan();//和男人那个....  
  13.   
  14. }  

 

一种类型嘛,那肯定是接口,定义个潘金莲

Java代码   收藏代码
  1. package com.yangguangfu.proxy;  
  2. /** 
  3.  *  
  4.  * @author 阿福([email protected])
     
  5.  *定义一个潘金莲是什么样的人 
  6.  */  
  7. public class PanJinLian  implements KindWoman{  
  8.   
  9.     @Override  
  10.     public void happyWithMan() {  
  11.         System.out.println("潘金莲和男人在做那个...");  
  12.           
  13.     }  
  14.   
  15.     @Override  
  16.     public void makeEyesWithMan() {  
  17.         System.out.println("潘金莲抛媚眼...");  
  18.           
  19.     }  
  20.   
  21. }  

 

再定义个丑陋的王婆

Java代码   收藏代码
  1. package com.yangguangfu.proxy;  
  2. /** 
  3.  *  
  4.  * @author 阿福([email protected])
     
  5.  *王婆这个人老聪明了,她太老了,是个男人都看不上她, 
  6.  *但是她有智慧经验呀,他作为一类女人的代理! 
  7.  */  
  8. public class WangPo implements KindWoman {  
  9.       
  10.     private KindWoman kindWoman;  
  11.       
  12.     public WangPo(){  
  13.         //默认的话是潘金莲的代理  
  14.         this.kindWoman = new PanJinLian();  
  15.     }  
  16.     //她可以是KindWomam的任何一个女人的代理,只要你是这一类型  
  17.     public WangPo(KindWoman kindWoman){  
  18.         this.kindWoman = kindWoman;  
  19.     }  
  20.   
  21.     @Override  
  22.     public void happyWithMan() {  
  23.         //自己老了,干不了了,但可以叫年轻的代替。  
  24.         this.kindWoman.happyWithMan();  
  25.           
  26.     }  
  27.   
  28.     @Override  
  29.     public void makeEyesWithMan() {  
  30.         //王婆年纪大了,谁看她抛媚眼啊  
  31.         this.kindWoman.makeEyesWithMan();  
  32.           
  33.     }  
  34.   
  35. }  
 

两个女主角都上场了,该男主角了,定义个西门庆

Java代码   收藏代码
  1. package com.yangguangfu.proxy;  
  2. /** 
  3.  *  
  4.  * @author 阿福([email protected])
     
  5.  *水浒传是这样写的:西门庆被潘金莲用竹竿敲了一下,西门庆看痴迷了,被王婆看到了,就开始撮合两人好事,王婆作为潘金莲的代理人收了不少好处费,那我们假设一下: 
  6.  *如果没有王婆在中间牵线,这两个不要脸的能成事吗?难说得很! 
  7.  */  
  8. public class XiMenQiang {  
  9.   
  10.     /** 
  11.      * @param args 
  12.      */  
  13.     public static void main(String[] args) {  
  14.         WangPo wangPo;  
  15.         //把王婆叫出来  
  16.          wangPo = new WangPo();  
  17.         //然后西门庆说,我要和潘金莲Happy,然后王婆就安排了西门庆丢筷子哪出戏:  
  18.         wangPo.makeEyesWithMan();  
  19.         //看到没有表面是王婆在做,其实爽的是潘金莲  
  20.         wangPo.happyWithMan();  
  21.           
  22.           
  23.   
  24.     }  
  25.   
  26. }  
 

那这就是活生生的一个例子,通过代理人实现了某种目的,如果真去了王婆这个中间环节,直接西门庆和潘金莲勾搭,估计很难成就武松杀嫂事件。

那我们再考虑一下,水浒里面还有没有这类型的女人?有,卢俊义的老婆贾氏(就是和那个管家苟合的那个),这个名字起的:“贾氏”,那我们也让王婆做她的代理:

Java代码   收藏代码
  1. package com.yangguangfu.proxy;  
  2. /** 
  3.  *  
  4.  * @author 阿福([email protected])
     
  5.  *定义一个贾氏是什么样的人 
  6.  */  
  7. public class JiaShi implements KindWoman {  
  8.   
  9.     @Override  
  10.     public void happyWithMan() {  
  11.         System.out.println("贾氏和男人在做那个...");  
  12.           
  13.     }  
  14.   
  15.     @Override  
  16.     public void makeEyesWithMan() {  
  17.         System.out.println("贾氏抛媚眼...");  
  18.           
  19.     }  
  20.   
  21.   
  22. }  
 

西门庆勾潘金莲又勾引贾氏

Java代码   收藏代码
  1. package com.yangguangfu.proxy;  
  2. /** 
  3.  *  
  4.  * @author 阿福([email protected])
     
  5.  *水浒传是这样写的:西门庆被潘金莲用竹竿敲了一下,西门庆看痴迷了,被王婆看到了,就开始撮合两人好事,王婆作为潘金莲的代理人收了不少好处费,那我们假设一下: 
  6.  *如果没有王婆在中间牵线,这两个不要脸的能成事吗?难说得很! 
  7.  */  
  8. public class XiMenQiang {  
  9.   
  10.     /** 
  11.      * @param args 
  12.      */  
  13.     public static void main(String[] args) {  
  14.         WangPo wangPo;  
  15.         //把王婆叫出来  
  16.          wangPo = new WangPo();  
  17.         //然后西门庆说,我要和潘金莲Happy,然后王婆就安排了西门庆丢筷子哪出戏:  
  18.         wangPo.makeEyesWithMan();  
  19.         //看到没有表面是王婆在做,其实爽的是潘金莲  
  20.         wangPo.happyWithMan();  
  21.           
  22.           
  23.           
  24.         //西门庆勾引贾氏  
  25.         JiaShi jiaShi = new JiaShi();  
  26.         wangPo = new WangPo(jiaShi);  
  27.         wangPo.makeEyesWithMan();  
  28.         wangPo.happyWithMan();  
  29.   
  30.     }  
  31.   
  32. }  

 说完这个故事,那我总结一下,代理模式主要使用了java的多态,干活的是被代理类,代理类主要是接活,你让我干活,好,我交给幕后的类去干,你满意就成,那怎么知道被代理类能不能干呢?同根就成,大家知根知底,你能做啥,我能做啥都清楚得很,同样一个接口呗。好了不多说了,慢慢体会吧。


 

你可能感兴趣的:(java)