zoukankan      html  css  js  c++  java
  • 大话设计模式C++版——代理模式

        本篇開始前先发个福利,程杰的《大话设计模式》一书高清电子版(带文件夹)已上传至CSDN,免积分下载。


    下载地址:http://download.csdn.net/detail/gufeng99/8843487

        代理模式是一种比較简单但却有用的设计模式,他能够灵活的更换代理的对象,但保证功能的完整性,就如卖衣服的代理商,他能够代理美特斯邦威的衣服,假设美特斯邦威的衣服被大家吐槽不好卖了,他还能够换去代理卖佐丹奴的。但无论怎么更换,还是能满足大家的需求——买衣服。
        以下以大话设计模式书中的样例为例。设计一个代理帮小明送花给小红。



    1、根据接口编程,设计代理对象的接口

    class IPursuit
    {
    public:
    	virtual	~IPursuit()	{}
    
    	virtual	void	SendFlowers() = 0;
    };

    2、代理类。也继承代理对象类,保持接口一致
    class CProxy : public IPursuit
    {
    public:
    	CProxy() : m_poIPursuit(NULL)	{}
    	~CProxy()
    	{
    		if (m_poIPursuit)
    		{
    			delete	m_poIPursuit;
    			m_poIPursuit = NULL;
    		}
    	}
    	
    	void	SetPursuit(IPursuit* poIPursuit)
    	{
    		//假设有旧的代理,要先删除。否则会造成内存泄漏
    		if (m_poIPursuit)
    		{
    			delete	m_poIPursuit;
    		}
    
    		m_poIPursuit = poIPursuit;
    	}
    
    	void	SendFlowers()
    	{
    		if (m_poIPursuit)
    		{
    			printf("Proxy help ");
    			m_poIPursuit->SendFlowers();
    		}
    	}
    
    private:
    	IPursuit*	m_poIPursuit;
    };
        代理类实际上啥也没干,仅仅是对相同的函数调用了一手被代理的对象的相应函数,当了一回二传手的角色。这里要注意代理对象因为会在代理中被释放,所以代理的对象一律必须是new出来的,即需在堆上创建的。


    3、被代理对象类

    class CPursuit : public IPursuit
    {
    public:
    	CPursuit(TString tstrName) : m_tstrName(tstrName) {}
    	~CPursuit()	{}
    
    	void	SendFlowers()
    	{
    		_tprintf(_T("%s sent flowers to Xiaohong
    "), m_tstrName.c_str());
    	}
    
    private:
    	TString	m_tstrName;
    };
    另附上TString宏
    #ifdef  UNICODE
    	#define	TString	std::wstring
    #else
    	#define	TString	std::string
    #endif
    4、測试演示样例
    void	Test()
    {
    	IPursuit*	poIXiaoMing = new CPursuit(_T("XiaoMing"));
    	CProxy		oCProxy;
    	
    	oCProxy.SetPursuit(poIXiaoMing);
    	oCProxy.SendFlowers();
    }
    5、代理类的应用
        这个样例非常形象,但却非常难看出代理模式的应用和长处。

    实际上在《大话设计模式C++版——抽象工厂模式》中有一个操作数据库管理员工信息的样例,因为可能会在使用数据库的过程中切换数据库。如曾经用的MySql,可能某个客户要求支持Access,这时就得进行切换了,此时用代理模式一样能够实现。
    5.1 代理模式实现员工数据库管理类对数据库的切换

    typedef	struct Employee 
    {
    	int		nID;
    	TString	tstrName;
    };
    
    class IEmployee
    {
    public:
    	~IEmployee()	{}
    	
    	virtual	bool		InserttoDB(Employee& stEmployee) = 0;
    	virtual	Employee	GetEmployee(int nID) = 0;
    };
    
    class CProxy : public IEmployee
    {
    public:
    public:
    	CProxy() : m_poIEmployee(NULL)	{}
    	~CProxy()
    	{
    		if (m_poIEmployee)
    		{
    			delete	m_poIEmployee;
    			m_poIEmployee = NULL;
    		}
    	}
    	
    	void		SetEmployee(IEmployee* poIEmployee)
    	{
    		if (m_poIEmployee)
    		{
    			delete	m_poIEmployee;
    		}
    
    		m_poIEmployee = poIEmployee;
    	}
    
    	bool		InserttoDB(Employee& stEmployee)
    	{
    		if (m_poIEmployee)
    		{
    			return	m_poIEmployee->InserttoDB(stEmployee);
    		}
    		
    		return	false;
    	}
    
    	Employee	GetEmployee(int nID)
    	{
    		if (m_poIEmployee)
    		{
    			return	m_poIEmployee->GetEmployee(nID);
    		}
    		
    		Employee	stEmployee;
    		return	stEmployee;
    	}
    
    private:
    	IEmployee*	m_poIEmployee;
    };
    
    class CEmployeefromMysql : public IEmployee
    {
    public:
    	bool		InserttoDB(Employee& stEmployee)
    	{
    		_tprintf(_T("Insert employee %s into mysql
    "), stEmployee.tstrName.c_str());
    		return	true;
    	}
    	
    	Employee	GetEmployee(int nID)
    	{
    		Employee	stEmployee;
    		printf("Get an employee from mysql by id %d
    ", nID);
    		return	stEmployee;
    	}
    };
    
    class CEmployeefromAccess : public	IEmployee
    {
    public:
    	bool		InserttoDB(Employee& stEmployee)
    	{
    		_tprintf(_T("Insert employee %s into access
    "), stEmployee.tstrName.c_str());
    		return	true;
    	}
    	
    	Employee	GetEmployee(int nID)
    	{
    		Employee	stEmployee;
    		printf("Get an employee from access by id %d
    ", nID);
    		return	stEmployee;
    	}
    };
    5.2 使用演示样例
    void	DataBaseTest()
    {
    	IEmployee*	poIEmployee = new CEmployeefromMysql();
    	CProxy		oCProxy;
    
    	oCProxy.SetEmployee(poIEmployee);
    	
    	Employee	stEmployee;
    	stEmployee.nID = 1;
    	stEmployee.tstrName = _T("Jim");
    	
    	oCProxy.InserttoDB(stEmployee);
    	
    	//切换数据库对象
    	poIEmployee	= new	CEmployeefromAccess();
    	
    	oCProxy.SetEmployee(poIEmployee);
    	oCProxy.InserttoDB(stEmployee);
    }
        从使用演示样例中就能够看出,代理类支持客户使用过程中动态切换数据库,这是和工厂模式最大的一点不同。特别适用于在常常须要切换类似对象模式的地方。
  • 相关阅读:
    VIJOS-P1340 拯救ice-cream(广搜+优先级队列)
    uva 11754 Code Feat
    uva11426 GCD Extreme(II)
    uvalive 4119 Always an Interger
    POJ 1442 Black Box 优先队列
    2014上海网络赛 HDU 5053 the Sum of Cube
    uvalive 4795 Paperweight
    uvalive 4589 Asteroids
    uvalive 4973 Ardenia
    DP——数字游戏
  • 原文地址:https://www.cnblogs.com/jhcelue/p/6825574.html
Copyright © 2011-2022 走看看