1. 动机
- 在面向对象系统中,有些对象由于某些原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问会给使用者、或者系统结构带来很多麻烦。
- 如何在不失去透明操作对象的同时来管理/控制这些对象特有的复杂性?增加一层间接层是软件开发中常见的解决方式。
2. 模式定义
为其他对象提供一种代理以控制(隔离,使用接口)对这个对象的访问。
----《设计模式》GOF
3. 结构
Client是需要使用RealSubject的,正常情况下,Client需要声明一个Subject的指针,然后new的时候,new RealSubject,但是由于某种场景的限制,比如前面说的安全考虑,或者访问控制,不能直接去new这个具体的对象,这个时候,就可以使用Proxy,让Cline去生成一个Proxy的对象,在Proxy里面做一些额外的操作,然后再去调动RealSubject的接口。
4. 代码示例
原始版本:
class ISubject{
public:
virtual void process();
};
class RealSubject : public ISubject{
public:
virtual void process(){
//...
// ...
}
};
class ClientApp{
ISubject *subject;
public:
ClientApp()
{
subject = new RealSubject();
}
void DoTask(){
// ...
subject->process();
// ...
}
};
但是由于某些原因,subject不能直接按照方面的方式进行new RealSubject
代码Ver2:
class SubjectProxy : public ISubject{
ISubject *subject;
public:
virtual void process(){
//...
// 对RealSubject的一种间接访问
subject->process();
// ...
}
};
class ClientApp{
ISubject *subject;
public:
ClientApp()
{
subject = new SubjectProxy();
}
void DoTask(){
// ...
subject->process();
// ...
}
};
上面Ver2示例代码中代理模式维护了一个RealSubject的指针,但是一般情况下,可能不会这么用,而是更复杂的方式使用,不过这种使用方式也是可以的。
4. 要点总结
- “增加一层间接层”是软件系统中对很多复杂问题的一种常见解决方法。在面向对象系统中,直接使用某些对象会带来很多问题,作为间接层的proxy对象便是解决这一问题的常用手段
- 具体proxy模式的实现方法、实现粒度都差别很大(即上面ver2代码中SubjectProxy的process方法),有些可能对打个对象做细粒度的控制,如copy on write技术,有些可能对组件模块提供抽象代理层,在架构层次对对象做proxy
(有些可能对组件模块提供抽象代理层,在架构层次对对象做proxy展开讲解:比如分布式系统,会大量的使用代理模式,举例,你要访问一个webService,这个webService比如说是amazon的webService你访问它,包括像现在非常流行的rust的这种架构,你拿到rust接口,比如新浪、微博、amazon、微信的一些rust接口,你在c++里面进行访问,往往会有一定的工具会帮你生成针对那个接口在客户端的代理类,那个代理类往往不是手工写,往往是工具自动实现的,手工写非常之复杂,因为你要控制所有网络访问的细节)
- proxy并不一定要求保持接口完整的一致性,只要能够实现间接控制,有时候损及一些透明度是可以接受的