C++设计模式之代理模式

    IPhone 6已经在中国香港开售了,圆了在专卖店等候一个多月苹果粉丝的苹果梦。然而对中国大陆而言,需要到9月17日苹果才在大陆开售。这对中国大陆的粉丝而言,不亚于一种煎熬,因此而滋生一种代购方式。很多中国大陆的苹果粉托在香港的朋友代为购买,或者中介在中国香港购买苹果后,转卖给大陆的苹果粉。在设计模式中,也存在一种类似的模式,当客户端无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口,称之为代理模式。     

1、代理模式概述

    代理模式定义如下:

代理模式:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。

    代理模式是一种对象结构型模式。在代理模式中引入了一个新的代理对象,代理对象在客户端对象和目标对象之间起到中介的作用,它去掉客户不能看到的内容和服务或者增添客户需要的额外的新服务。

    代理模式的结构比较简单,其核心是代理类,为了让客户端能够一致性地对待真实对象和代理对象,在代理模式中引入了抽象层。

    代理模式包含如下三个角色:

    (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.主要优点
    (1)当如果需要在访问真实主题时增加新的访问控制机制和新功能,只需增加一个新的代理类,在客户端代码中使用新增代理类即可,源代码无须修改,符合开闭原则。
    (2)客户端可以一致的对待真实主题对象和代理主题对象,符合针对接口编程原则,降低系统的耦合度。
    (3)客户端不需要直接访问真实主题,而由代理对象间接处理,符合"迪迷特法则"。
    (4)代理对象维持一个真实对象的引用,它们是一种组合关系,符合多用组合少用继承原则。
2.主要缺点

    代理模式的主要缺点如下:

    (1)由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢

    (2)实现代理模式需要额外的工作,而且有些代理模式的实现过程较为复杂,例如远程代理

3.代理模式具体应用

    (1)斗地主游戏托管功能,把游戏交由系统处理,由系统决定是否出牌。

    (2)网络图片查看器的开发:一般输入网址下载图片比较耗时,通过代理,当输入网址的时候,只显示图标,双击图标才从网络上下载图片并显示。

    (3)本例中水灾报警系统的开发。

    (4)车票查询功能开发: 已经开发好了一个查询模块,现在需要添加身份验证模块,以及查询Log模块,把查询的信息记录到Log文件中,可以使用代理模式复用已经开发好的那个查询模块。

    (5)生活中的代理: 酒后代驾、求律师打官司、淘宝京东等网上代购网站、房屋中介等。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值