动机

在面向对象系统中,有些对象由于某种原因,直接访问会给使用者、或者系统结构带来很多麻烦
某种原因是哪些呢?比如

  1. 对象创建的开销很大
  2. 某些操作需要安全控制
  3. 需要进程外的访问
    1. 比如在分布式系统中,你所用的对象是在另一个机器上创建的,你都不可能对它进行直接访问

如果在不失去透明操作对象的同时,来管理/控制这些对象特有的复杂性?增加一层间接层是软件开发中常用的解决方式

  • 不失去透明操作:就是一致性,接口没有变,我可以像使用原对象一样使用代理层
  • 管理/控制:代理层内部帮我们做一些复杂的操作,我们通过和原来一样的接口,就能完成管理/控制这些对象

模式定义

为其他对象提供一种代理以控制(隔离,隔离的方式就是使用接口)对这个对象的访问——《设计模式》GoF

结构

image.png
Subject是一个接口

  • Subject名字改成ISubject会好理解些

Client使用Subject时,真正创建和使用的应该是RealSubject这个对象

  • Subject* p = new RealSubject

但是由于某种特殊的原因

  • 可能要对RealSubject做性能优化
  • 可能要在RealSubject基础上做一些安全控制
  • 可能RealSubject是在另一个机器上,Client都不能直接使用RealSubject

这个时候

  • Client就应该去访问Proxy
  • Proxy去调用RealSubject,并扩展一些其他的内容(比如性能优化、安全控制)

示例

原始代码

  1. //接口
  2. class ISubject{
  3. public:
  4. virtual void process();
  5. };
  6. //实现ISubject
  7. class RealSubject: public ISubject{
  8. public:
  9. virtual void process(){
  10. //业务逻辑处理
  11. //...
  12. }
  13. };
  14. //客户端程序
  15. class ClientApp{
  16. ISubject* subject;
  17. public:
  18. ClientApp(){
  19. //创建RealSubject
  20. //这里可以使用工厂,或者其他方式,反正就是绕来绕去创建到一个RealSubject
  21. subject=new RealSubject();
  22. }
  23. void DoTask(){
  24. //...
  25. subject->process();
  26. //....
  27. }
  28. };

这样写,可能遇到以下情况

  1. RealSubject在别的进程(甚至另一个计算机)中,你无法直接访问
  2. 要在RealSubject基础上做一些性能优化、安全控制等等

那就可以使用代理模式

优化:代理模式

增加一个代理层Proxy,客户端程序使用Proxy,而不使用RealSubject

  1. //接口
  2. class ISubject{
  3. public:
  4. virtual void process();
  5. };
  6. //Proxy,一个代理层
  7. class SubjectProxy: public ISubject{
  8. public:
  9. virtual void process(){
  10. //对RealSubject的一种间接访问
  11. //1. 如果RealSubject在另一个进程或别的计算机中,需要通过网络层实现调用
  12. //2. 其他一些事情,如性能优化、安全控制
  13. //....
  14. }
  15. };
  16. //客户端
  17. class ClientApp{
  18. ISubject* subject;
  19. public:
  20. ClientApp(){
  21. //使用Proxy,而不直接使用RealSubject
  22. subject=new SubjectProxy();
  23. }
  24. void DoTask(){
  25. //...
  26. subject->process();
  27. //....
  28. }
  29. };

要点总结

“增加一层间接层”是软件系统中对许多复杂问题的一种常见解决方法。在面向对象系统中,直接使用某些对象会带来很多问题,作为间接层的proxy对象便是解决这一问题的常用手段。

具体Proxy设计模式的实现方法、实现粒度都相差很大,有些可能对单个对象做细粒度的控制,如copy-on-write技术,有些可能对组件模式提供抽象代理层,在架构层次对对象做proxy。

Proxy并不一定要求保持接口完整的一致性,只要能够实现间接控制,有时损失一些透明性是可以接受的。

在实际开发中,有一些工具能够帮我们实现代理类

  • C++使用REST架构时,有一些工具能够帮我们生成REST接口的代理类(这些代理类往往不是手工写的,手工写非常复杂,你要控制所有网络访问的细节),生成之后,在C++层面使用代理类是非常方便的