zoukankan      html  css  js  c++  java
  • 大话设计模式C++版——表驱动法改造简单工厂

    上回《大话设计模式C++版——简单工厂模式》中指出了简单工厂模式的缺陷,即违背了开发—封闭原则,其主要原因是由于switch的判断结构的使用,使修改或添加新的对象时需要改动简单工厂类的代码,如何改造switch结构,表驱动法就可以粉墨登场了。

    表驱动法的介绍见《数据驱动编程之表驱动法》。


    1、面向接口编程,先改造抽象接口类IOperation

    class IOperation
    {
    public:
    	IOperation() : m_nNuml(0), m_nNumr(0) {}
    	virtual	~IOperation() {}
    	
    	virtual	void	SetNum(int nNuml = 0, int nNumr = 0)
    	{
    		m_nNuml = nNuml;
    		m_nNumr = nNumr;
    	}
    
    	virtual	int		CalculateResult() = 0;
    
    public:
    	typedef	IOperation* (CALLBACK* fn_CreateObject)();
    
    protected:
    	int	m_nNuml, m_nNumr;
    };

    接口基本无改动,由于表驱动法中需要在表中填入驱动函数接口,故先定义一个该接口函数的定义,用于产生具体接口对象。


    2、改造接口对象类

    class COperation_Add : public IOperation
    {
    public:
    	int		CalculateResult()
    	{
    		return	m_nNuml + m_nNumr;
    	}
    
    	static	IOperation*	CALLBACK CreateObject()
    	{
    		return	new	COperation_Add();
    	}
    };
    
    
    class COperation_Dec : public IOperation
    {
    public:
    	int		CalculateResult()
    	{
    		return	m_nNuml - m_nNumr;
    	}
    
    	static	IOperation*	CALLBACK CreateObject()
    	{
    		return	new	COperation_Dec();
    	}
    };

    增加了CreateObject()静态函数,改函数的作用是用来产生本对象。由于表驱动函数是用于回调的,所以需要定义为静态回调函数。


    3、改造工厂类,增加驱动表改造switch结构(重点)

    class CClassFactory
    {
    public:
    	CClassFactory() {}
    	virtual ~CClassFactory() {}
    	
    	BOOL	AddOperationFunc(char cOperation, IOperation::fn_CreateObject func)
    	{
    		if (func)
    		{
    			m_mapOperationFunc[cOperation] = func;
    			return	TRUE;
    		}
    		
    		return	FALSE;
    	}
    
    	IOperation*	CreateObject(char cOperation)
    	{
    		IOperation::fn_CreateObject	func = m_mapOperationFunc[cOperation];
    
    		if (func)
    		{
    			return	func();
    		}
    
    		return	NULL;
    	}
    
    protected:
    	std::map<char, IOperation::fn_CreateObject>	m_mapOperationFunc; //用map实现驱动表
    };

    工厂类中的switch消失了,换成了在map中以操作符为key找对应驱动函数,然后进行调用。同时增加了添加新操作符和对应驱动函数的接口AddOperationFunc(),这样如果需要新增加对象或者修改操作符对应的驱动函数,调用此接口即可,灵活性大大增加。


    4、使用示例

    void	Test()
    {
    	CClassFactory	oCClassFactory;
    	IOperation*		poIOperation = NULL;
    	
    
    	//添加对象工厂的生产对象
    	oCClassFactory.AddOperationFunc('+', COperation_Add::CreateObject);
    	oCClassFactory.AddOperationFunc('-', COperation_Dec::CreateObject);
    
    	poIOperation = oCClassFactory.CreateObject('+');
    	
    	if (poIOperation)
    	{
    		poIOperation->SetNum(2, 3);
    		printf("2 + 3 = %d
    ", poIOperation->CalculateResult());
    		
    		delete poIOperation;
    	}
    
    	poIOperation = oCClassFactory.CreateObject('-');
    
    	if (poIOperation)
    	{
    		poIOperation->SetNum(2, 3);
    		printf("2 + 3 = %d
    ", poIOperation->CalculateResult());
    		
    		delete poIOperation;
    	}
    }

    使用前需添加操作符和对应的驱动函数,这样一来将用户的任务加重了,而且需要用户认识的类增加了,封装性降低了。是否可进一步改进?


    5、进一步改进简单工厂类,提高封装性

    class CNewClassFactory : CClassFactory
    {
    public:
    	virtual	~CNewClassFactory()	{}
    
    	virtual	void	Init()
    	{
    		AddOperationFunc('+', COperation_Add::CreateObject);
    		AddOperationFunc('-', COperation_Dec::CreateObject);
    	}
    };

    新简单工厂类中,增加了一个初始化函数Init(),代替用户的进行操作符和对应的驱动函数,这样用户只需要调用Init()函数即可,封装性进一步提高,那么有同学可能会问,如果要增加新的计算对象,还不得改动Init()函数代码,这不跑了一圈又回到没改造前的原点了。

    这就得用到开放—封闭原则了,新简单工厂类CNewClassFactory中,我们将Init()函数申明为虚函数了,如果我们要增加新的计算对象,可以有2个途径:

    5.1用户在自己代码中调用AddOperationFunc()函数进行添加。

    5.2继承新简单工厂类,重写Init()函数。


    本文为博主原创文章,如需转载请说明转至http://www.cnblogs.com/organic/
  • 相关阅读:
    5.win上安装ES
    6.入门案例:电商网站商品管理(一)
    BZOJ 1616 [Usaco2008 Mar]Cow Travelling游荡的奶牛:dp【网格型】
    BZOJ 1626 [Usaco2007 Dec]Building Roads 修建道路:kruskal(最小生成树)
    BZOJ 1614 [Usaco2007 Jan]Telephone Lines架设电话线:spfa + 二分【路径中最大边长最小】
    BZOJ 1612 [Usaco2008 Jan]Cow Contest奶牛的比赛:floyd传递闭包
    BZOJ 1609 [Usaco2008 Feb]Eating Together麻烦的聚餐:LIS & LDS (nlogn)
    POJ 2976 Dropping tests:01分数规划【二分】
    BZOJ 1607 [Usaco2008 Dec]Patting Heads 轻拍牛头:统计 + 筛法【调和级数】
    BZOJ 1605 [Usaco2008 Open]Crisis on the Farm 牧场危机:dp【找转移路径】
  • 原文地址:https://www.cnblogs.com/organic/p/5005647.html
Copyright © 2011-2022 走看看