[设计模式]静态代理实现

  1. 云栖社区>
  2. 博客>
  3. 正文

[设计模式]静态代理实现

技术小哥哥 2017-11-14 20:56:00 浏览651
展开阅读全文

代理模式的定义:

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,如需转载请自行联系原作者

网友评论

登录后评论
0/500
评论