简说设计模式——代理模式

1、什么是代理模式

  关于代理模式,咱们听到的见到的最多的可能就是静态代理、动态代理之类的,固然还有你们都知道的Spring Aop,这里咱们先不谈这些个代理,先说个简单的例子。游戏代练应该都据说过,许多人确定也找过代练,曾经DNF、LOL、COC等等游戏的代练不少,固然如今各种游戏层出不穷,也都有各类代练,那这里所谓的代练是什么?就是Proxy,也即代理类,那游戏代练这件事就是一个代理模式。html

  若是以为很差理解能够这么想,代练的流程是,你把本身的帐号交给代练人员,让他们帮你打怪升级,而你只须要提供帐号便可。那代练人员那边,他所要作的就是登录你的帐号,而后替你打游戏,从第三者的角度来看,你这个角色在打怪升级,但这个第三者并不知道是否是你本人在打游戏,他只能看到你这个帐号正在打怪升级,但并不须要知道后面打游戏的是谁。这就是代理模式,由他人代理玩游戏。git

  若是以为这个还很差理解,那再说一个例子。假设我如今要邀请明星来上节目,我是直接给这个明星打电话吗?固然不是,是给他的经纪人打电话,而后再由经纪人通知到该明星,这里经纪人充当的就是代理的角色。设计模式

  更常见的例子就是Windows的快捷方式,经过快捷方式,咱们能够访问某个文件夹下的exe文件,这就是一个典型的代理模式,它将接口,按上面游戏的说法说就是代练的帐号,提供了出来,咱们只需点击快捷方式,它会帮咱们运行指定目录下的指定程序。说了这么多,如今来看一下代理模式的定义。安全

  代理模式(Proxy),为其余对象提供一种代理以控制对这个对象的访问。UML结构图以下:ide

 

  其中,Subject是主题角色,定义了RealSubject和Proxy的共同接口;RealSubject是具体主题角色,定义了Proxy所表明的真实实体;Proxy为代理主题角色,保存一个引用使代理能够访问实体,并提供一个与Subject的接口相同的接口。this

  1. Subject抽象类

  定义了RealSubject和Proxy的共同接口,这样就在任何使用RealSubject的地方均可以使用Proxy。spa

1 public abstract class Subject {
2 
3     public abstract void request();
4     
5 }

  2. RealSubject类

  定义了Proxy所表明的真实实体。设计

1 public class RealSubject extends Subject {
2 
3     @Override
4     public void request() {
5         System.out.println("真实的请求RealSubject");
6     }
7 
8 }

  3. Proxy类

  代理类。一个代理类能够代理多个被委托者或被代理者,所以一个代理类具体代理哪一个真实主题角色,是由场景类决定的。代理

 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 }

   4. Client客户端

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很相似,能够相互对照一下。

2、代理模式的应用

  1. 什么时候使用

  • 想在访问一个类的时候作一些控制时

   2. 方法

  • 增长中间层

   3. 优势

  • 职责清晰。真实的角色就是实现实际的业务逻辑,不用担忧其余非本职责的事务
  • 高扩展性。代理类彻底能够在不作任何修改的状况下使用
  • 智能化。好比动态代理

   4. 缺点

  • 有些类型的代理模式可能会形成请求的处理速度变慢
  • 实现代理模式须要额外的工做,有些代理模式的实现很是复杂

   5. 使用场景

  • 远程代理。为一个对象在不一样的地址空间提供局部表明
  • 虚拟代理。根据须要建立开销很大的对象,经过它来存放实例化须要很长时间的真实对象
  • 安全代理。用来控制真实对象访问时的权限
  • 智能指引,当调用真实的对象时,代理处理另一些事

   6. 应用实例

  • 游戏代练
  • 邀请明星,联系其经纪人
  • Windows快捷方式
  • 火车票代售点
  • Spring AOP

   7. 注意事项

  • 与适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口
  • 与装饰模式区别:装饰模式是为了加强功能,而代理模式是为了加以控制

 3、代理模式的实现

  这里咱们就以上面说过的游戏代练为例。UML图以下:

  1. IGamePlayer类

  游戏玩家接口。由登录、杀怪、升级三个方法。

1 public interface IGamePlayer {
2     //登录
3     public void login(String user, String password);
4     //杀怪
5     public void killBoss();
6     //升级
7     public void upgrade();
8 }

   2. GamePlayer类

  游戏玩家。正常玩家登录、打怪、升级。

 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 }

   3. GamePlayerProxy类

  游戏代练。也即代理类,用于代替玩家登录、打怪、升级。

 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 }

  4. Client客户端

  玩家找了一个代练,代练登录了该玩家的帐号,而后替该玩家打怪升级。

 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 }

   运行结果以下:

  

  从这个结果咱们只能看到有人登录了这个帐号,他正在打怪升级,但并不知道是否是代练,这就是代理模式。

  有关代理模式的延伸(静态代理、动态代理)详见《简说设计模式——代理模式(续)》

 

  源码地址:https://gitee.com/adamjiangwh/GoF

相关文章
相关标签/搜索