代理模式定义如下:
代理模式:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。 |
代理模式是一种对象结构型模式。在代理模式中引入了一个新的代理对象,代理对象在客户端对象和目标对象之间起到中介的作用,它去掉客户不能看到的内容和服务或者增添客户需要的额外的新服务。
代理模式的结构比较简单,其核心是代理类,为了让客户端能够一致性地对待真实对象和代理对象,在代理模式中引入了抽象层。
代理模式包含如下三个角色:
(1) Subject(抽象主题角色):它声明了真实主题和代理主题的共同接口,这样一来在任何使用真实主题的地方都可以使用代理主题,客户端通常需要针对抽象主题角色进行编程。
(2) Proxy(代理主题角色):它包含了对真实主题的引用,从而可以在任何时候操作真实主题对象;在代理主题角色中提供一个与真实主题角色相同的接口,以便在任何时候都可以替代真实主题;代理主题角色还可以控制对真实主题的使用,负责在需要的时候创建和删除真实主题对象,并对真实主题对象的使用加以约束。通常,在代理主题角色中,客户端在调用所引用的真实主题操作之前或之后还需要执行其他操作,而不仅仅是单纯调用真实主题对象中的操作。
(3) RealSubject(真实主题角色):它定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的操作。
2、水位报警系统的设计与实现
某软件公司需要设计一个水位报警系统,需求如下: 能够实时采集水位的变化,把采集到的水位变化以图片的方式传回;图像处理模块将对采集回来的图片进行处理,用以确定是否发布水灾报警; 可以将图像处理模块处理后的图像显示出来。现在已经开发好了图像处理模块,请用代理模式设计该系统。 |
IWaterDetection充当抽象主题角色,RealWaterDetection充当真实主题角色,ProxyWaterDetection充当代理主题角色。IWaterDetection水位监测抽象类提供一个虚方法,对采集到的水位图像进行处理,具体处理过程由真实水位监测对象RealWaterDetection进行处理。IWaterDetection水位监测抽象类实现代码如下:
//水位检测抽象类
class IWaterDetection
{
public:
//对采集后的水位图像处理,以判断是否发布水灾安全警报
virtual void ImageProcess() = 0;
};
RealWaterDetection真实水位监测对象将对采集后的水位图像进行处理,实现了真实的业务逻辑,ImageProcess是图像处理的业务方法。实现代码如下:
//水位检测真实对象类
class RealWaterDetection : public IWaterDetection
{
public:
//对采集后的水位图像处理,以判断是否发布水灾安全警报
void ImageProcess()
{
cout << "------对采集后的水位图像信息进行处理,以判断是否发布水灾安全警报" << endl;
}
};
ProxyWaterDetection水位检测代理对象,维持了一个真实水位监测对象的引用。在对图像进行处理时,先采集水位图像,然后调用真实水位监测对象的图像处理方法,最后将处理后的图像显示出来。实现代码如下:
//水位检测代理对象类
class ProxyWaterDetection : public IWaterDetection
{
private:
//维持一个对真实水位检测对象的引用
IWaterDetection * m_pRealWaterDetection;
public:
ProxyWaterDetection()
{
m_pRealWaterDetection = new RealWaterDetection();
}
~ProxyWaterDetection()
{
if( NULL != m_pRealWaterDetection )
{
delete m_pRealWaterDetection;
m_pRealWaterDetection = NULL;
}
}
//采集水位图像
void CollectWaterLevelImage()
{
cout << "采集水位图像" << endl;
}
//显示处理后的水位图像
void DisplayWaterLevelImage()
{
cout << "显示处理后的水位图像" << endl;
}
//对采集后的水位图像处理,以判断是否发布水灾安全警报
void ImageProcess()
{
CollectWaterLevelImage();
//调用真实水位检测对象的图像处理方法
m_pRealWaterDetection->ImageProcess();
DisplayWaterLevelImage();
}
};
测试代码实现如下:
#include <iostream>
#include "WaterDetection.h"
using namespace std;
int main()
{
//创建一个代理对象
IWaterDetection * pProxyWaterDetection = new ProxyWaterDetection();
//调用代理对象的图像处理方法
pProxyWaterDetection->ImageProcess();
//销毁操作
delete pProxyWaterDetection;
pProxyWaterDetection = NULL;
return 0;
}
编译并运行结果如下:
3、代理模式总结
抽象主题声明了真实主题和代理主题的共同接口,这样一来在任何使用真实主题的地方都可以使用代理主题,客户端通常需要针对抽象主题角色进行编程。真实主题角色中实现了真实的业务操作,而代理主题维持了一个真实主题的引用,当客户端调用代理主题的方法时,将调用真实主题的业务方法。代理主题相当于一个中介,实际主要操作还是得委托给真实主题进行处理。代理模式的主要缺点如下:
(1)由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢
(2)实现代理模式需要额外的工作,而且有些代理模式的实现过程较为复杂,例如远程代理
3.代理模式具体应用
(1)斗地主游戏托管功能,把游戏交由系统处理,由系统决定是否出牌。
(2)网络图片查看器的开发:一般输入网址下载图片比较耗时,通过代理,当输入网址的时候,只显示图标,双击图标才从网络上下载图片并显示。
(3)本例中水灾报警系统的开发。
(4)车票查询功能开发: 已经开发好了一个查询模块,现在需要添加身份验证模块,以及查询Log模块,把查询的信息记录到Log文件中,可以使用代理模式复用已经开发好的那个查询模块。
(5)生活中的代理: 酒后代驾、求律师打官司、淘宝京东等网上代购网站、房屋中介等。