Proxy 代理模式也是属于“接口隔离”模式,通过增加一层间接层来解决问题的模式。
文章目录
- 1. 动机( Motivation)
- 2. 模式定义
- 3. 结构( Structure )
- 4. 代码演示Proxy 代理模式
- 4.1 常规方法
- 4.2 Proxy 代理模式
- 5. 要点总结
- 6. 其他参考
1. 动机( Motivation)
-
在面向对象系统中,有些对象由于某种原因 (比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等)直接访问会给使用者、或者系统结构带来很多麻烦。
-
如何在不失去透明操作对象的同时来管理/控制这些对象特有的复杂性?
增加一层间接层
是软件开发中常见的解决方式。
所谓透明操作
就是一致性,假如本来访问这个对象的方式是new一个对象,调用对象接口,那我还用类似方式访问你,至于背后的麻烦事,都不用知道,实现隔离。
2. 模式定义
为其他对象提供一种代理以控制(隔离,使用接口
) 对这个对象的访问。
—《设计模式》GoF
3. 结构( Structure )
上图是《设计模式》GoF中定义的Proxy 代理模式的设计结构。结合上面的代码看图中最重要的是看其中稳定和变化部分,也就是下图中红框和蓝框框选的部分。
模式的结构很简单,但在实际使用过程中,可能会变得非常复杂。上图中接口为Subject
,实际的对象为RealSubject
,本来进行访问时,Client应该是直接声明一个Subject
的接口,真正实际创建的是一个RealSubject
的对象,但是由于某种特殊的原因,这时Client就应该直接去访问Proxy
,Proxy
和RealSubject
之间背后要做的事情很复杂。
4. 代码演示Proxy 代理模式
4.1 常规方法
以下是一个简单的示意性的例子,按照常规的做法,创建接口,RealSubject作为实际对象,ClientApp直接声明一个Subject
的接口,真正实际创建的是一个RealSubject
的对象。
client.cpp
//接口
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();
//....
}
};
这种方式是不合适的,可能是由于性能、安全控制、分布式等原因,无法达到new RealSubject();
此时应该怎么去做呢?
4.2 Proxy 代理模式
使用Proxy 代理模式模式的做法如下:
proxy.cpp
class ISubject{
public:
virtual void process();
};
//Proxy的设计
class SubjectProxy: public ISubject{
public:
virtual void process(){
//对RealSubject的一种间接访问
//....
}
};
class ClientApp{
ISubject* subject;
public:
ClientApp(){
subject=new SubjectProxy();
}
void DoTask(){
//...
subject->process();
//....
}
};
proxy.cpp有时候是自己写,有时候是使用工具生成的。创建接口class SubjectProxy: public ISubject
,SubjectProxy
实现一种对RealSubject的间接访问,在class ClientApp
中创建subject=new SubjectProxy();
, SubjectProxy()针对RealSubject()的代理。
Proxy 代理模式常常会设计的比较复杂,但是整体的设计思想要进行理解。
5. 要点总结
- “增加一层间接层”是软件系统中对许多复杂问题的一种常见解决方法。在面向对象系统中,直接使用某些对象会带来很多问题,作为间接层的proxy对象便是解决这一问题的常用手段。
- 具体proxy设计模式的实现方法、实现粒度都相差很大,有些可能对单个对象做细粒度的控制,如copy-on-write技术,有些可能对组件模块提供抽象代理层,在架构层次对对象做proxy。
具体到实际中,以下代码的差异度相当大,总体设计思想遵循:代理类(SubjectProxy)和实际类(RealSubject)的接口(ISubject)是一致的
virtual void process(){
//对RealSubject的一种间接访问
//....
}
copy-on-write技术:字符串类中经常如此去做,如果对象没有什么更改的话,复制的话,内部会生成一个指针指向原来的对象,每拷贝一次都是浅拷贝,这种共享在当你需要改这个对象时就是有问题的,此时你就需要内部拷贝一份,实现一种代理
在分布式系统中会大量使用Proxy 代理模式
- Proxy并不一定要求保持接口完整的一致性,只要能够实现间接控制,有时候损及一些透明性是可以接受的。
代理的核心思想是增加一个中间层,实现不为外界所知的功能
6. 其他参考
C++设计模式——代理模式