Java 设计模式 代理模式

https://blog.csdn.net/luanlouis/article/details/18847313

https://blog.csdn.net/luanlouis/article/details/24589193

Proxy (代理模式)定义

Purpose (目的)

  • 为另外一个对象提供一个代理或占位符以控制对这个对象的访问。

Structure (结构)

  

  • Proxy角色
    1. (该角色)持有一个RealSubject 角色的引用,用以访问RealSubject。如果RealSubject和Subject角色的接口是相同的,Proxy角色也可以持有一个Subject的引用(不过这个Subject 还是引用的是RealSubject的实现,即父类引用子类对象 :Subject subject=new RealSubject())。
    2. 应该具有和Subject角色完全一致的接口,这样,Proxy角色可以成为RealSubject 的替代品。
    3. 控制对 真正对象访问,并且可以负责创建和删除真正对象。
    4. 其他功能:
    5. 远程代理负责加密请求和参数,然后将加密的请求发送到不同的地址空间的真正对象。
    6. 为真正的对象提供额外的信息。
    7. 保护性质的代理可以为 访问 realSubject请求提供权限控制。
  • Subject : 定义RealSubject和Proxy实现的公共接口。
  • RealSubject : 定义代理要表示的真正的对象。

Applications(应用)

  • 一个远程的代理对不同的地址空间内的对象提供一个本地表示。
  •  可以根据需求控制创建代价昂贵的对象。
  • 为原对象提供访问权限的控制。

Consequences(结论)

  • 代理模式 引入了非直接访问对象的机制 。这种添加的非直接访问,有以下几种应用:
    1. 一个远程的代理对不同的地址空间内的对象提供一个本地表示
    2. 一个虚拟的代理可以优化功能,比如根据需求创建对象。
    3. 保护性代理允许当访问对象时,做一些额外的内部操作。

代理模式应用示例


想要访问某对象,但是不能直接访问某对象场景--车票代售点

     车站设置代售点的原因,一方面是为人流高峰期缓解车站自身压力,另一方面则是对一些偏远地方,购票很不方便的人提供便利。

    

      车站的售票业务主要有:卖票、问询、退票,将其抽象出一个接口TicketService,将功能分别定义为:sellTicket(),inquire()和withdraw()。将车站定义为Station类,实现TicketService接口;而代售点定义为StationProxy,实现TicketService接口,并持有一个Station实例的引用,三个角色之间的关系如下图:


相关代码如下:

[java]  view plain  copy
  1. package com.foo.proxy;  
  2. /** 
  3.  * 售票服务接口  
  4.  * @author louluan 
  5.  */  
  6. public interface TicketService {  
  7.   
  8.     //售票  
  9.     public void sellTicket();  
  10.       
  11.     //问询  
  12.     public void inquire();  
  13.       
  14.     //退票  
  15.     public void withdraw();  
  16.       
  17. }  

[java]  view plain  copy
  1. package com.foo.proxy;  
  2.   
  3. /** 
  4.  * 售票服务接口实现类,车站 
  5.  * @author louluan 
  6.  */  
  7. public class Station implements TicketService {  
  8.   
  9.     @Override  
  10.     public void sellTicket() {  
  11.         System.out.println("\n\t售票.....\n");  
  12.   
  13.     }  
  14.   
  15.     @Override  
  16.     public void inquire() {  
  17.         System.out.println("\n\t问询。。。。\n");  
  18.     }  
  19.   
  20.     @Override  
  21.     public void withdraw() {  
  22.         System.out.println("\n\t退票......\n");  
  23.     }  
  24.   
  25. }  

[java]  view plain  copy
  1. package com.foo.proxy;  
  2.   
  3. /** 
  4.  * 车票代售点 
  5.  * @author louluan 
  6.  * 
  7.  */  
  8. public class StationProxy implements TicketService {  
  9.   
  10.     private Station station;  
  11.   
  12.     public StationProxy(Station station){  
  13.         this.station = station;  
  14.     }  
  15.       
  16.     @Override  
  17.     public void sellTicket() {  
  18.   
  19.         // 1.做真正业务前,提示信息  
  20.         this.showAlertInfo("××××您正在使用车票代售点进行购票,每张票将会收取5元手续费!××××");  
  21.         // 2.调用真实业务逻辑  
  22.         station.sellTicket();  
  23.         // 3.后处理  
  24.         this.takeHandlingFee();  
  25.         this.showAlertInfo("××××欢迎您的光临,再见!××××");  
  26.   
  27.     }  
  28.   
  29.     @Override  
  30.     public void inquire() {  
  31.         // 1做真正业务前,提示信息  
  32.         this.showAlertInfo("××××欢迎光临本代售点,问询服务不会收取任何费用,本问询信息仅供参考,具体信息以车站真实数据为准!××××");  
  33.         // 2.调用真实逻辑  
  34.         station.inquire();  
  35.         // 3。后处理  
  36.         this.showAlertInfo("××××欢迎您的光临,再见!××××");  
  37.     }  
  38.   
  39.     @Override  
  40.     public void withdraw() {  
  41.         // 1。真正业务前处理  
  42.         this.showAlertInfo("××××欢迎光临本代售点,退票除了扣除票额的20%外,本代理处额外加收2元手续费!××××");  
  43.         // 2.调用真正业务逻辑  
  44.         station.withdraw();  
  45.         // 3.后处理  
  46.         this.takeHandlingFee();  
  47.   
  48.     }  
  49.   
  50.     /* 
  51.      * 展示额外信息 
  52.      */  
  53.     private void showAlertInfo(String info) {  
  54.         System.out.println(info);  
  55.     }  
  56.   
  57.     /* 
  58.      * 收取手续费 
  59.      */  
  60.     private void takeHandlingFee() {  
  61.         System.out.println("收取手续费,打印发票。。。。。");  
  62.     }  
  63.   
  64. }  
[java]  view plain  copy
  1. package com.foo.proxy;  
  2. /** 
  3.  * 客户端角色 
  4.  * @author louluan 
  5.  */  
  6. public class Client {  
  7.   
  8.     public static void main(String[] args) {  
  9.   
  10.         //创建Station  
  11.         Station service = new Station();  
  12.         //创建代理类  
  13.         StationProxy proxy = new StationProxy(service);  
  14.         //代售点售票  
  15.         proxy.sellTicket();  
  16.     }  
  17.   
  18. }  
执行结果:



为访问对象增加权限-用户信息检索系统

      公司有一个用户信息检索系统,管理员可以检索用户的基本信息,教育背景,和账户信息。由于业务发展的需要,此系统要跟公司实现信息共享,需要向别的公司提供我们的接口,但是信息共享并不是全部共享,只允许别的公司查询基本信息和教育背景,而有些敏感信息账户信息不允许别的公司调用的,在这里可以设置一个代理,用于控制访问查询信息接口的权限控制,当是外部想要查询账户信息时,给你返回 "********"掩码展示。

定义一个UserInfoService接口,有getBasicInfo(),getEducationalBackground(),getAcccountInfo()分别用于查询基本信息,教育背景,账户信息;

UserInfoServiceImpl类实现UserInfoService接口;

UserInfoServiceProxy类作为代理类,实现UserInfoService接口和持有一个UserInfoServiceImpl引用:


[java]  view plain  copy
  1. package com.foo.proxy1;  
  2.   
  3. /** 
  4.  * 信息查询接口 
  5.  */  
  6. public interface UserInfoService {  
  7.   
  8.     //基本信息  
  9.     public String getBasicInfo();  
  10.     //教育背景  
  11.     public String getEducationalBackground();  
  12.     //账户信息  
  13.     public String getAcccountInfo();  
  14. }  

[java]  view plain  copy
  1. package com.foo.proxy1;  
  2. /** 
  3.  * 查询接口实现 
  4.  * @author louluan 
  5.  */  
  6.   
  7. public class UserInfoServiceImpl implements UserInfoService {  
  8.   
  9.     @Override  
  10.     public String getBasicInfo() {  
  11.         return "Basic Info....";  
  12.     }  
  13.   
  14.     @Override  
  15.     public String getEducationalBackground() {  
  16.         return "Educational Background.....";  
  17.     }  
  18.   
  19.     @Override  
  20.     public String getAcccountInfo() {  
  21.         return "Account Info.....";  
  22.     }  
  23.   
  24. }  

[java]  view plain  copy
  1. package com.foo.proxy1;  
  2.   
  3. /** 
  4.  * 信息查询代理控制访问权限 
  5.  * @author louluan 
  6.  */  
  7. public class UserInfoServiceProxy implements UserInfoService {  
  8.   
  9.     private UserInfoService impl;  
  10.     private String role;  
  11.     public UserInfoServiceProxy(UserInfoService impl,String role)  
  12.     {  
  13.         this.impl = impl;  
  14.         this.role = role;  
  15.     }  
  16.     @Override  
  17.     public String getBasicInfo() {  
  18.         return impl.getBasicInfo();  
  19.     }  
  20.   
  21.     @Override  
  22.     public String getEducationalBackground() {  
  23.         return impl.getEducationalBackground();  
  24.     }  
  25.   
  26.     @Override  
  27.     public String getAcccountInfo() {  
  28.         //如果是公司本部,返回  
  29.         if("1".equals(role))  
  30.         {  
  31.             return impl.getAcccountInfo();  
  32.         }  
  33.         //禁止访问impl方法,返回****               
  34.         return "**********";  
  35.     }  
  36. }  

[java]  view plain  copy
  1. package com.foo.proxy1;  
  2.   
  3. public class Client {  
  4.   
  5.     public static String OUT="0";  
  6.     public static String IN="0";  
  7.       
  8.     public static void main(String[] args) {  
  9.         UserInfoService service = new UserInfoServiceImpl();  
  10.           
  11.         UserInfoServiceProxy proxy = new UserInfoServiceProxy(service,OUT);  
  12.         //外部公司查询信息  
  13.         System.out.println("*****外部公司查询信息*******");  
  14.         //获取基本信息:  
  15.         String basicInfo = proxy.getBasicInfo();  
  16.         System.out.println("基本信息:"+basicInfo);  
  17.         //教育背景  
  18.         String educationalBackground = proxy.getEducationalBackground();  
  19.         System.out.println("教育背景:"+educationalBackground);  
  20.         //账户信息  
  21.         String accountInfo = proxy.getAcccountInfo();  
  22.         System.out.println("账户信息:"+accountInfo);  
  23.     }  
  24. }  

增强原对象的功能---AOP

代理模式最有魅力的地方就在于它实现了AOP(Aspect-Oriented  Programming),即面向切面的编程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值