代理模式也叫委托模式。
代理模式定义:对其他对象提供一种代理从而控制对这个对象的访问。就是,代理类 代理 被代理类,来执行被代理类里的方法。
一般情况下,代理模式化有三个角色。
1,抽象的主题类(或者接口) IGamePlayer
2,代理类。
3,被代理类。
下面以游戏玩家代理为例。
一,先来看下最基本的代理模式。
代码如下:
主题接口:
1 package com.yemaozi.proxy.base; 2 3 //游戏玩家主题接口 4 public interface IGamePlayer { 5 //登录游戏 6 public void login(String username, String password); 7 8 //击杀Boss 9 public void killBoss(); 10 11 //升级 12 public void upGrade(); 13 }
被代理类:
1 package com.yemaozi.proxy.base; 2 3 //需要代理的主题类。 4 public class GamePlayer implements IGamePlayer{ 5 6 private String name = ""; 7 8 public GamePlayer(String name){ 9 this.name = name; 10 } 11 12 public void login(String username, String password) { 13 System.out.println("登录名为 "+username+" 进入游戏," + name + " 登录成功!"); 14 } 15 16 public void killBoss() { 17 System.out.println(this.name + " 击杀了Boss!"); 18 } 19 20 public void upGrade() { 21 System.out.println(this.name + "升级了!"); 22 } 23 24 }
代理类:
1 package com.yemaozi.proxy.base; 2 3 //代理类 4 //代理也是个游戏玩家,所以也要实现IGamePlayer 5 public class ProxyGamePlayer implements IGamePlayer{ 6 7 private IGamePlayer proxyGp = null; 8 9 //代理需要获取被代理的信息,就是执行被代理所要执行的方法, 10 //所以要获取被代理的对象。这里通过构造方法获取。 11 public ProxyGamePlayer(GamePlayer gp){ 12 this.proxyGp = gp; 13 } 14 15 public void login(String username, String password) { 16 System.out.println("代理登录的游戏!"); 17 proxyGp.login(username, password); 18 } 19 20 public void killBoss() { 21 proxyGp.killBoss(); 22 } 23 24 public void upGrade() { 25 proxyGp.upGrade(); 26 } 27 }
先来看下不用代理类的场景类:
1 package com.yemaozi.proxy.base; 2 3 //这是正常的,用非代理的情况下。 4 public class Client { 5 public static void main(String [] args){ 6 IGamePlayer gp = new GamePlayer("张三"); 7 //开始执行主题接口中的方法。 8 //登录游戏 9 gp.login("zhangsan", "123456"); 10 //杀怪 11 gp.killBoss(); 12 //升级 13 gp.upGrade(); 14 } 15 } 16 17 执行结果: 18 登录名为 zhangsan 进入游戏,张三 登录成功! 19 张三 击杀了Boss! 20 张三升级了!
游戏也有玩累,玩乏的时候,所以找个代练来升级。下面就是代理类的场景类。
1 package com.yemaozi.proxy.base; 2 3 //代理客户端 4 public class BasePoxyClient { 5 public static void main(String[] args){ 6 IGamePlayer proxyGp = new ProxyGamePlayer(new GamePlayer("张三")); 7 proxyGp.login("zhangsan", "123456"); 8 proxyGp.killBoss(); 9 proxyGp.upGrade(); 10 } 11 } 12 13 执行结果为: 14 代理登录的游戏! 15 登录名为 zhangsan 进入游戏,张三 登录成功! 16 张三 击杀了Boss! 17 张三升级了!
执行还是这样,但是可以看出,确实是代理类来执行的。这就是最简单的代理模式了。
代理模式还是有很多种的,比如,普通代理模式,强制代理模式,虚拟代理模式,动态代理模式.....
接下来我们一一来看。
二,普通代理模式:
其实普通代理模式和上面的差不多。
普通代理模式,它不用知道代理的真实角色是谁,屏蔽了真实角色的更变对高层模块的影响。
(本例中,就是,不用知道为谁代练游戏,只需要知道代练游戏的用户名,密码即可。)
代码如下:
抽象主题类或者接口:
1 package com.yemaozi.proxy.common; 2 3 /** 4 * 普通代理模式:就是我们要知道代理的存在,然后才能访问(或者使用代理)。 5 * 对于基本的代理改动较小。只改变实现类中 6 * @author yemaozi 7 */ 8 public interface IGamePlayer { 9 //登录游戏 10 public void login(String username, String password); 11 12 //击杀Boss 13 public void killBoss(); 14 15 //升级 16 public void upGrade(); 17 }
需要被代理类:
1 package com.yemaozi.proxy.common; 2 3 public class GamePlayer implements IGamePlayer{ 4 5 private String name = ""; 6 7 //通过构造方法,将代理传递进来。 8 public GamePlayer(IGamePlayer proxyGp, String name){ 9 if(proxyGp == null){ 10 //处理非正常情况。 11 }else{ 12 this.name = name; 13 } 14 } 15 //登录游戏 16 public void login(String username, String password) { 17 System.out.println("登录名为 "+username+" 进入游戏," + name + " 登录成功!"); 18 } 19 //杀Boss 20 public void killBoss() { 21 System.out.println(this.name + " 击杀了Boss!"); 22 } 23 24 //升级 25 public void upGrade() { 26 System.out.println(this.name + "升级了!"); 27 } 28 29 }
代理类:
1 package com.yemaozi.proxy.common; 2 3 public class ProxyGamePlayer implements IGamePlayer{ 4 5 private IGamePlayer proxyGp = null; 6 7 public ProxyGamePlayer(String name){ 8 9 try { 10 //通过构造方法创建GamePlayer,同时将自己传递进去。用于在GamePlayer判断业务逻辑 11 proxyGp = new GamePlayer(this, name); 12 } catch (Exception e) { 13 e.printStackTrace(); 14 } 15 } 16 17 public void login(String username, String password) { 18 System.out.println("代理登录的游戏!"); 19 proxyGp.login(username, password); 20 } 21 22 public void killBoss() { 23 proxyGp.killBoss(); 24 } 25 26 public void upGrade() { 27 proxyGp.upGrade(); 28 } 29 30 }
看下场景类:
1 package com.yemaozi.proxy.common; 2 3 /** 4 * 普通代理模式,它不用知道代理的真实角色是谁,屏蔽了真实角色的更变对高层模块的影响。 5 * (本例中,就是,不用知道为谁代练游戏,只需要知道代练游戏的用户名,密码即可。) 6 * @author yemaozi 7 * 8 */ 9 public class Client { 10 public static void main(String[] args){ 11 IGamePlayer proxyGp = new ProxyGamePlayer("张三"); 12 proxyGp.login("zhangsan", "123456"); 13 proxyGp.killBoss(); 14 proxyGp.upGrade(); 15 } 16 } 17 18 执行结果: 19 代理登录的游戏! 20 登录名为 zhangsan 进入游戏,张三 登录成功! 21 张三 击杀了Boss! 22 张三升级了!
在场景类中,我们发现,我们并不需要知道具体为谁代理,把被代理类进行了隐藏。所以,被代理若是有所修改,只要实现了对应接口中的方法,则不会影响代理的执行。