博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[设计模式]静态代理实现
阅读量:5902 次
发布时间:2019-06-19

本文共 8113 字,大约阅读时间需要 27 分钟。

代理模式的定义:

Provide a surrogate or placeholder for another to control access to it.(为其他对象提供一种代理以控制对这个对象的访问)

代理模式也叫委托模式,许多的其他模式,如状态模式,策略模式,访问者模式本质上是在更特殊的场合采用了委托模式,而且在日常的应用中,代理模式可以提供非常好的访问控制.

在一些著名的开源软件中也经常见到它的身影,如Struts2的Form元素映射就是采用了代理模式(准确的说是动态代理模式),Struts2的拦截器,Spring 的AOP.

代理模式的使用场景:

现实世界中,打官司要找律师,你不想参与中间过程的是是非非,只要完成自己的答辩就可以,其他的事情事前调查,事后追查都由律师来搞定,这就是为了减轻你的负担.

Spring的AOP就是一个非常典型的动态代理.

代理模式的扩展:

(类比)网络上的代理服务器分为透明代理和普通代理. 透明代理就是用户不用设置代理服务器地址,就可以直接访问,也就是说代理服务器对用户来说是透明的,不用知道它存在的.

普通代理则是需要用户自己设置代理服务器的IP地址,用户必须知道代理的存在.

我们设计模式在红的普通代理和强制代理也是类似的结构.普通代理就是我们要知道代理的存在.然后才能访问.(类比网络的普通代理)

强制代理这是调用者直接调用真实角色,而不 用关心代理是否存在.其代理的产生是由真是角色决定的.(类比网络的透明代理)

普通代理

要求客户端只能访问代理角色,而不能访问真实角色.

上面的GamePlayer的构造函数增加了_gamePlayer参数,而代理角色GamePlayerProxy则只要传入代理者的名字即可,而不是需要说是替那个对象做代理.

普通代理的接口类:

1 /** 2  * 游戏玩家 3  */ 4 public interface IGamePlayer { 5  6     //登录游戏 7     public void login(String user,String password); 8      9     //杀怪,这是网络游戏的主要特色10     public void killBoss();11     12     //升级13     public void upgrade();14 }

普通代理中的游戏者:

1 /** 2  * 真是的玩家 3  */ 4 public class GamePlayer implements IGamePlayer { 5     private String name = ""; 6      7     //构造函数限制谁能创建对象,并同时传递姓名 8     public GamePlayer(IGamePlayer _gamePlayer,String _name) throws Exception{ 9         if(_gamePlayer == null ){10             throw new Exception("不能创建真是角色!");11         }else{12             this.name = _name;13         }14         15     }16     //打怪,最期望的就是杀老怪17     public void killBoss() {18         System.out.println(this.name + "在打怪!");19     }20     21     //进游戏之前你肯定要登录吧,这是一个必要条件22     public void login(String user, String password) {23         System.out.println("登录名为"+user + " 的用户 " + this.name + "登录成功!");24     }25 26     //升级,升级有很多方法,花钱买是一种,做任务也是一种27     public void upgrade() {28         System.out.println(this.name + " 又升了一级!");29     }30 31 }

普通代理中的代理者:

1 /** 2  * 代练者 3  */ 4 public class GamePlayerProxy implements IGamePlayer { 5     private IGamePlayer gamePlayer = null; 6      7     //通过构造函数传递要对谁进行代练 8     public GamePlayerProxy(String name){ 9         try {10             gamePlayer = new GamePlayer(this,name);11         } catch (Exception e) {12             // TODO 异常处理13         }14     }15     16     //代练杀怪17     public void killBoss() {18         this.gamePlayer.killBoss();19     }20 21     //代练登录22     public void login(String user, String password) {23         this.gamePlayer.login(user, password);24 25     }26 27     //代练升级28     public void upgrade() {29         this.gamePlayer.upgrade();30 31     }32 33 }

普通代理的场景类:

1 /** 2  * 场景类 3  */ 4 public class Client { 5  6     public static void main(String[] args) { 7  8         //然后再定义一个代练者 9         IGamePlayer proxy = new GamePlayerProxy("张三");10         11         //开始打游戏,记下时间戳12         System.out.println("开始时间是:2009-8-25 10:45");13         proxy.login("zhangSan", "password");14         //开始杀怪15         proxy.killBoss();16         //升级17         proxy.upgrade();18         //记录结束游戏时间19         System.out.println("结束时间是:2009-8-26 03:40");20         21     }22 23 }

打印输出:

开始时间是:2009-8-25 10:45

登录名为zhangSan 的用户 张三登录成功!
张三在打怪!
张三 又升了一级!
结束时间是:2009-8-26 03:40

 

强制代理:

强制代理在设计模式中比较另类,一般的思维都是通过代理找到真实的角色的,但是强制代理却是要"强制",你必须通过真实角色查找到代理角色,否则你不能访问.

只有通过真实角色指定的代理类才可以访问,也就是由真实角色管理代理角色.

高层模块new了一个真实角色的对象,返回的却是代理角色.

这好比你和一个明星比较熟,相互认识,有件事情你需要想她确认一下,于是你就直接拨通了明星的电话:

"喂,沙比呀,我要见一下XXX导演,你帮下忙!"
"不行呀衰哥,我这几天很忙呀,你找我的经纪人吧......"
郁闷了吧,你是想直接绕过她的代理,谁知道返回的还是她的代理,这就是强制代理.

修改一下IGamePlayer接口,增加一个getProxy的方法.

强制代理的接口类:

1 /** 2  * 游戏玩家 3  */ 4 public interface IGamePlayer { 5  6     //登录游戏 7     public void login(String user,String password); 8      9     //杀怪,这是网络游戏的主要特色10     public void killBoss();11     12     //升级13     public void upgrade();14     15     //每个人都可以找一下自己的代理 指定要访问自己必须通过哪个代理16     public IGamePlayer getProxy();17 }

强制代理的真实角色:

1 /** 2  * 真是的玩家 3  */ 4 public class GamePlayer implements IGamePlayer { 5     private String name = ""; 6     //我的代理是谁 7     private IGamePlayer proxy = null; 8          9     public GamePlayer(String _name){10         this.name = _name;    11     }12     13     //找到自己的代理14     public IGamePlayer getProxy(){15         this.proxy = new GamePlayerProxy(this);16         return this.proxy;17     }18     19     //打怪,最期望的就是杀老怪20     public void killBoss() {21         if(this.isProxy()){22             System.out.println(this.name + "在打怪!");23         }else{24             System.out.println("请使用指定的代理访问");25         }26         27     }28     29     //进游戏之前你肯定要登录吧,这是一个必要条件30     public void login(String user, String password) {31         if(this.isProxy()){32             System.out.println("登录名为"+user + " 的用户 " + this.name + "登录成功!");33         }else{34             System.out.println("请使用指定的代理访问");;35         }36         37     }38 39     //升级,升级有很多方法,花钱买是一种,做任务也是一种40     public void upgrade() {41         if(this.isProxy()){42             System.out.println(this.name + " 又升了一级!");43         }else{44             System.out.println("请使用指定的代理访问");45         }46     }47     48     //校验是否是代理访问  检查自己是否是指定的代理,指定的代理则允许访问,否则不允许访问.49     private boolean isProxy(){50         if(this.proxy == null){51             return false;52         }else{53             return true;54         }55     }56 }

强制代理的代理类:

1 /** 2  * 代练者 3  */ 4 public class GamePlayerProxy implements IGamePlayer { 5     private IGamePlayer gamePlayer = null; 6      7     //构造函数传递用户名 8     public GamePlayerProxy(IGamePlayer _gamePlayer){     9         this.gamePlayer = _gamePlayer;10     }11     12     //代练杀怪13     public void killBoss() {14         this.gamePlayer.killBoss();15     }16 17     //代练登录18     public void login(String user, String password) {19         this.gamePlayer.login(user, password);20 21     }22 23     //代练升级24     public void upgrade() {25         this.gamePlayer.upgrade();26 27     }28     29     //代理的代理暂时还没有,就是自己30     public IGamePlayer getProxy(){31         return this;32     }33 }

(错误一:)直接访问真实角色:

1 /** 2  * 场景类(直接访问真实角色) 3  */ 4 public class Client { 5     public static void main(String[] args) { 6         //定义个游戏的角色 7         IGamePlayer player = new GamePlayer("张三"); 8          9         //开始打游戏,记下时间戳10         System.out.println("开始时间是:2009-8-25 10:45");11         player.login("zhangSan", "password");12         //开始杀怪13         player.killBoss();14         //升级15         player.upgrade();16         //记录结束游戏时间17         System.out.println("结束时间是:2009-8-26 03:40");18         19     }20 }

打印输出:

开始时间是:2009-8-25 10:45

请使用指定的代理访问
请使用指定的代理访问
请使用指定的代理访问
结束时间是:2009-8-26 03:40

必须通过代理类访问,不能直接访问.

(错误二:)直接访问代理类:

1 /** 2  * 场景类(直接访问代理类) 3  */ 4 public class Client { 5     public static void main(String[] args) { 6         //定义个游戏的角色 7         IGamePlayer player = new GamePlayer("张三"); 8         //然后再定义一个代练者 9         IGamePlayer proxy = new GamePlayerProxy(player);10         11         //开始打游戏,记下时间戳12         System.out.println("开始时间是:2009-8-25 10:45");13         proxy.login("zhangSan", "password");14         //开始杀怪15         proxy.killBoss();16         //升级17         proxy.upgrade();18         //记录结束游戏时间19         System.out.println("结束时间是:2009-8-26 03:40");20         21     }22 }

打印输出:

开始时间是:2009-8-25 10:45

请使用指定的代理访问
请使用指定的代理访问
请使用指定的代理访问
结束时间是:2009-8-26 03:40

这个代理类不是真实角色指定的对象(代理类),这个代理对象(类)是你自己new出来的,当然真实对象不认了,这就好比是那个明星,人家告诉你去找她的代理人了,你随便找个代理人能成吗?你必须去找她指定的代理才行.

(正确:)强制代理的场景类:

1 /** 2  * 场景类 3  */ 4 public class Client { 5  6     public static void main(String[] args) { 7         //定义个游戏的角色 8         IGamePlayer player = new GamePlayer("张三"); 9         //获得指定的代理10         IGamePlayer proxy = player.getProxy();11         //开始打游戏,记下时间戳12         System.out.println("开始时间是:2009-8-25 10:45");13         proxy.login("zhangSan", "password");14         //开始杀怪15         proxy.killBoss();16         //升级17         proxy.upgrade();18         //记录结束游戏时间19         System.out.println("结束时间是:2009-8-26 03:40");20     }21 }

打印输出:

开始时间是:2009-8-25 10:45

登录名为zhangSan 的用户 张三登录成功!
张三在打怪!
张三 又升了一级!
结束时间是:2009-8-26 03:40

 

OK,可以正常访问代理了.强制代理的概念就是要从真实角色查找到代理角色,不允许直接访问真实角色.高层模块只要调用getProxy就可以访问真实角色的所有方法,它根本就不需要一产生一个代理出来,代理的管理已经由真实的角色自己完成.

本文转自SummerChill博客园博客,原文链接:http://www.cnblogs.com/DreamDrive/p/5408401.html,如需转载请自行联系原作者

你可能感兴趣的文章
2019年移动开发,我的改变之旅
查看>>
华为海思回应「极限生存的假设成为现实」
查看>>
【我读《Big Data》】序言部分--拥抱“大数据时代”
查看>>
初识HTML
查看>>
10月30日云栖精选夜读:云栖大会Serverless场分享:日志处理挑战与展望
查看>>
J 位操作练习 (Java)
查看>>
跟着项目学 android canvas——InDoorView 地图引擎
查看>>
JavaScript 代码简洁之道
查看>>
iOS开发,解决上传照片按原图旋转了90度的问题
查看>>
CardView改变阴影颜色
查看>>
关于微信JSSDK中遇到的“invalid signature”的天坑
查看>>
vue脚手架中集成less
查看>>
vue分环境打包
查看>>
css flexbox 布局调试
查看>>
React-Native 开发总结
查看>>
初见函数式编程
查看>>
红黑树--(高清无码图+代码)演示
查看>>
Mac配置Redis
查看>>
MySQL数据库锁介绍
查看>>
vue中this.$router.push()传参简单说明
查看>>