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

    IPhone 6已经在中国香港开售了,圆了在专卖店等候一个多月苹果粉丝的苹果梦。然而对中国大陆而言。须要到9月17日苹果才在大陆开售。这对中国大陆的粉丝而言,不亚于一种煎熬,因此而滋生一种代购方式。

非常多中国大陆的苹果粉托在香港的朋友代为购买,或者中介在中国香港购买苹果后。转卖给大陆的苹果粉。在设计模式中。也存在一种类似的模式,当client无法直接訪问某个对象或訪问某个对象存在困难时能够通过一个代理对象来间接訪问,为了保证client使用的透明性,所訪问的真实对象与代理对象须要实现同样的接口,称之为代理模式。     


1、代理模式概述

    代理模式定义例如以下:

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

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

    代理模式的结构比較简单。其核心是代理类,为了让client可以一致性地对待真实对象和代理对象,在代理模式中引入了抽象层。

    代理模式包括例如以下三个角色:

    (1) Subject(抽象主题角色):它声明了真实主题和代理主题的共同接口,这样一来在不论什么使用真实主题的地方都能够使用代理主题。client通常须要针对抽象主题角色进行编程。

    (2) Proxy(代理主题角色):它包括了对真实主题的引用。从而能够在不论什么时候操作真实主题对象;在代理主题角色中提供一个与真实主题角色同样的接口,以便在不论什么时候都能够替代真实主题。代理主题角色还能够控制对真实主题的使用,负责在须要的时候创建和删除真实主题对象,并对真实主题对象的使用加以约束。

通常,在代理主题角色中。client在调用所引用的真实主题操作之前或之后还须要运行其它操作。而不不过单纯调用真实主题对象中的操作。

    (3) RealSubject(真实主题角色):它定义了代理角色所代表的真实对象。在真实主题角色中实现了真实的业务操作,client能够通过代理主题角色间接调用真实主题角色中定义的操作。


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、代理模式总结 

    抽象主题声明了真实主题和代理主题的共同接口,这样一来在不论什么使用真实主题的地方都能够使用代理主题,client通常须要针对抽象主题角色进行编程。真实主题角色中实现了真实的业务操作,而代理主题维持了一个真实主题的引用。当client调用代理主题的方法时,将调用真实主题的业务方法。

代理主题相当于一个中介,实际主要操作还是得托付给真实主题进行处理。

1.主要长处
    (1)当假设须要在訪问真实主题时添加新的訪问控制机制和新功能。仅仅需添加一个新的代理类,在client代码中使用新增代理类就可以,源码无须改动。符合开闭原则。
    (2)client能够一致的对待真实主题对象和代理主题对象,符合针对接口编程原则,减少系统的耦合度。
    (3)client不须要直接訪问真实主题。而由代理对象间接处理,符合"迪迷特法则"。

    (4)代理对象维持一个真实对象的引用。它们是一种组合关系。符合多用组合少用继承原则。
2.主要缺点

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

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

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

3.代理模式详细应用

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

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

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

    (4)车票查询功能开发: 已经开发好了一个查询模块。如今须要加入身份验证模块,以及查询Log模块。把查询的信息记录到Log文件里。能够使用代理模式复用已经开发好的那个查询模块。

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



原文地址:https://www.cnblogs.com/claireyuancy/p/6758088.html