关于代理模式,咱们听到的见到的最多的可能就是静态代理、动态代理之类的,固然还有你们都知道的Spring Aop,这里咱们先不谈这些个代理,先说个简单的例子。游戏代练应该都据说过,许多人确定也找过代练,曾经DNF、LOL、COC等等游戏的代练不少,固然如今各种游戏层出不穷,也都有各类代练,那这里所谓的代练是什么?就是Proxy,也即代理类,那游戏代练这件事就是一个代理模式。html
若是以为很差理解能够这么想,代练的流程是,你把本身的帐号交给代练人员,让他们帮你打怪升级,而你只须要提供帐号便可。那代练人员那边,他所要作的就是登录你的帐号,而后替你打游戏,从第三者的角度来看,你这个角色在打怪升级,但这个第三者并不知道是否是你本人在打游戏,他只能看到你这个帐号正在打怪升级,但并不须要知道后面打游戏的是谁。这就是代理模式,由他人代理玩游戏。git
若是以为这个还很差理解,那再说一个例子。假设我如今要邀请明星来上节目,我是直接给这个明星打电话吗?固然不是,是给他的经纪人打电话,而后再由经纪人通知到该明星,这里经纪人充当的就是代理的角色。设计模式
更常见的例子就是Windows的快捷方式,经过快捷方式,咱们能够访问某个文件夹下的exe文件,这就是一个典型的代理模式,它将接口,按上面游戏的说法说就是代练的帐号,提供了出来,咱们只需点击快捷方式,它会帮咱们运行指定目录下的指定程序。说了这么多,如今来看一下代理模式的定义。安全
代理模式(Proxy),为其余对象提供一种代理以控制对这个对象的访问。UML结构图以下:ide
其中,Subject是主题角色,定义了RealSubject和Proxy的共同接口;RealSubject是具体主题角色,定义了Proxy所表明的真实实体;Proxy为代理主题角色,保存一个引用使代理能够访问实体,并提供一个与Subject的接口相同的接口。this
定义了RealSubject和Proxy的共同接口,这样就在任何使用RealSubject的地方均可以使用Proxy。spa
1 public abstract class Subject { 2 3 public abstract void request(); 4 5 }
定义了Proxy所表明的真实实体。设计
1 public class RealSubject extends Subject { 2 3 @Override 4 public void request() { 5 System.out.println("真实的请求RealSubject"); 6 } 7 8 }
代理类。一个代理类能够代理多个被委托者或被代理者,所以一个代理类具体代理哪一个真实主题角色,是由场景类决定的。代理
1 public class Proxy extends Subject { 2 3 private RealSubject realSubject = null; 4 5 public Proxy() { 6 this.realSubject = new RealSubject(); 7 } 8 9 @Override 10 public void request() { 11 this.before(); 12 this.realSubject.request(); 13 this.after(); 14 } 15 16 //预处理 17 private void before() { 18 System.out.println("-------before------"); 19 } 20 21 //善后处理 22 private void after() { 23 System.out.println("-------after-------"); 24 } 25 }
1 public class Client { 2 3 public static void main(String[] args) { 4 Proxy proxy = new Proxy(); 5 proxy.request(); 6 } 7 8 }
运行结果以下:code
这个结果和Spring的AOP很相似,能够相互对照一下。
这里咱们就以上面说过的游戏代练为例。UML图以下:
游戏玩家接口。由登录、杀怪、升级三个方法。
1 public interface IGamePlayer { 2 //登录 3 public void login(String user, String password); 4 //杀怪 5 public void killBoss(); 6 //升级 7 public void upgrade(); 8 }
游戏玩家。正常玩家登录、打怪、升级。
1 public class GamePlayer implements IGamePlayer { 2 3 private String name = ""; 4 5 public GamePlayer(String name) { 6 this.name = name; 7 } 8 9 @Override 10 public void login(String user, String password) { 11 System.out.println("登陆名为<" + user + ">的用户<" + this.name + ">登录成功!"); 12 } 13 14 @Override 15 public void killBoss() { 16 System.out.println("<" + this.name + ">在打怪!"); 17 } 18 19 @Override 20 public void upgrade() { 21 System.out.println("<" + this.name + ">升了一级!"); 22 } 23 24 }
游戏代练。也即代理类,用于代替玩家登录、打怪、升级。
1 public class GamePlayerProxy implements IGamePlayer { 2 3 private IGamePlayer gamePlayer = null; 4 5 public GamePlayerProxy(IGamePlayer gamePlayer) { 6 this.gamePlayer = gamePlayer; 7 } 8 9 @Override 10 public void login(String user, String password) { 11 this.gamePlayer.login(user, password); 12 } 13 14 @Override 15 public void killBoss() { 16 this.gamePlayer.killBoss(); 17 } 18 19 @Override 20 public void upgrade() { 21 this.gamePlayer.upgrade(); 22 } 23 24 }
玩家找了一个代练,代练登录了该玩家的帐号,而后替该玩家打怪升级。
1 public class Client { 2 3 public static void main(String[] args) { 4 //定义一个玩家 5 IGamePlayer player = new GamePlayer("桐人"); 6 //定义一个代练 7 IGamePlayer proxy = new GamePlayerProxy(player); 8 9 //开始打游戏 10 //登录 11 proxy.login("adam", "123456"); 12 //开始杀怪 13 proxy.killBoss(); 14 //升级 15 proxy.upgrade(); 16 } 17 18 }
运行结果以下:
从这个结果咱们只能看到有人登录了这个帐号,他正在打怪升级,但并不知道是否是代练,这就是代理模式。
有关代理模式的延伸(静态代理、动态代理)详见《简说设计模式——代理模式(续)》。