您的位置:首页 > 其它

行为型模式:Strategy——策略模式

2011-05-17 12:26 295 查看

一、意图

定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换,本模式使得算法可独立于使用它的客户而变化——四人团

二、基本思想

定义算法家族,分别封装起来,让它们之间可以互相替换,让算法的变化,不会影响到使用算法的用户。

三、优缺点分析

GOOD:

(1)策略模式是一种定义一系列算法的方法,从概念上看,所有这些算法完成的都是相同的工作,只是实现不同。

所以使用策略模式,就可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。

(2)策略模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能

(3)简化了单元测试(因为每个算法都有自己的类,可以通过自己的接口单独测试)

BUG:客户端要做出判断使用哪个具体算法(可通过在context中与工厂模式的结合来消除这个问题,虽然当新增加需求时,还是要改context中的代码,但是任何需求的变更本身就是需要成本的

四、适用情况

策略模式和简单工厂基本相同,但简单工厂模式只能解决对象创建问题,对于类中的成员以方法为主,而且算法经常变动的类,应使用策略模式。

在实践中,策略模式实际上可以封装几乎任何类型的规则,只要在分析过程中听到需要不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。

五、标准UML图例及源码

(1)标准UML图列





(2)标准源码

/************************************************************************


* FileName: Strategy.h


* Author: steven oyj (steven.oyj@gmail.com)


* Description : 抽象算法类:定义所有支持的算法的公共接口


* Time: 2010/5/24


************************************************************************/


#ifndef STRATEGY_H


#define STRATEGY_H




class Strategy


{


public:


 virtual ~Strategy(){}


 // 算法方法


 virtual void AlgorithmInterface() = 0;


};


#endif


/************************************************************************


* FileName: Context.h


* Author: steven oyj (steven.oyj@gmail.com)


* Description : 上下文类,用一个ConcreateStrategy来配置,维护一个对Strategy对象的引用


* Time: 2010/5/24


************************************************************************/


#ifndef CONTEXT_H


#define CONTEXT_H




#include "Strategy.h"


#include <iostream>




class Context


{


public:


 Context(Strategy *pStrategy);// 构造时,传入具体的策略对象


 ~Context();




 void ContextInterface();// 根据具体的策略对象,调用其算法的方法


private:


 Strategy* m_pStrategy;


};




#endif // CONTEXT_H


 1:/************************************************************************



* FileName: ConcreateStrategyA.h


* Author: steven oyj (steven.oyj@gmail.com)


* Description : 具体算法类A:封装了具体的算法或行为,继承于Strategy


* Time: 2010/5/24


************************************************************************/


#ifndef CONCREATESTRATEGYA_H


#define CONCREATESTRATEGYA_H




#include "Strategy.h"


#include <iostream>




class ConcreateStrategyA


 : public Strategy


{


public:


 virtual ~ConcreateStrategyA(){}


// 算法A实现方法


 virtual void AlgorithmInterface();


};




#endif // CONCREATESTRATEGYA_H


/************************************************************************


* FileName: ConcreateStrategyB.h


* Author: steven oyj (steven.oyj@gmail.com)


* Description : 具体算法类B:封装了具体的算法或行为,继承于Strategy


* Time: 2010/5/24


************************************************************************/


#ifndef CONCREATESTRATEGYB_H


#define CONCREATESTRATEGYB_H




#include "Strategy.h"


#include <iostream>




class ConcreateStrategyB


 : public Strategy


{


public:


 virtual ~ConcreateStrategyB(){}


// 算法B实现方法


 virtual void AlgorithmInterface();


};




#endif // CONCREATESTRATEGYB_H


/************************************************************************


* FileName: ConcreateStrategyC.h


* Author: steven oyj (steven.oyj@gmail.com)


* Description : 具体算法C:封装了具体的算法或行为,继承于Strategy


* Time: 2010/5/24


************************************************************************/


#ifndef CONCREATESTRATEGYC_H


#define CONCREATESTRATEGYC_H




#include "Strategy.h"


#include <iostream>




class ConcreateStrategyC


 : public Strategy


{


public:


 virtual ~ConcreateStrategyC(){}


// 算法C实现方法


 virtual void AlgorithmInterface();


};




#endif // CONCREATESTRATEGYC_H


/************************************************************************


* FileName: Context.cpp


* Author: steven oyj (steven.oyj@gmail.com)


* Description : 上下文类的具体实现


* Time: 2010/5/24


************************************************************************/


#include "Context.h"




// 构造时,传入具体的策略对象


Context::Context(Strategy *pStrategy)


 : m_pStrategy(pStrategy)


{


}




Context::~Context()


{


 delete m_pStrategy;


 m_pStrategy = NULL;


}




// 根据具体的策略对象,调用其算法的方法


void Context::ContextInterface()


{


 if (NULL != m_pStrategy)


{


 m_pStrategy->AlgorithmInterface();


}


}


/************************************************************************


* FileName: ConcreateStrategyA.cpp


* Author: steven oyj (steven.oyj@gmail.com)


* Description : ConcreateStrategyA类的具体实现


* Time: 2010/5/24


************************************************************************/


#include "ConcreateStrategyA.h"




// 算法A实现方法


void ConcreateStrategyA::AlgorithmInterface()


{


 std::cout << "AlgorithmInterface Implemented by ConcreateStrategyA\n";


}


/************************************************************************


* FileName: ConcreateStrategyC.cpp


* Author: steven oyj (steven.oyj@gmail.com)


* Description : ConcreateStrategyC类的具体实现


* Time: 2010/5/24


************************************************************************/


#include "ConcreateStrategyC.h"




// 算法C实现方法


void ConcreateStrategyC::AlgorithmInterface()


{


 std::cout << "AlgorithmInterface Implemented by ConcreateStrategyC\n";


}


/************************************************************************


* FileName: ConcreateStrategyB.cpp


* Author: steven oyj (steven.oyj@gmail.com)


* Description : ConcreateStrategyB类的具体实现


* Time: 2010/5/24


************************************************************************/


#include "ConcreateStrategyB.h"




// 算法B实现方法


void ConcreateStrategyB::AlgorithmInterface()


{


 std::cout << "AlgorithmInterface Implemented by ConcreateStrategyB\n";


}


/************************************************************************


* FileName: Main.cpp


* Author: steven oyj (steven.oyj@gmail.com)


* Description : Strategy模式的测试代码


* Time: 2010/5/24


************************************************************************/


#include "Context.h"


#include "ConcreateStrategyA.h"


#include "ConcreateStrategyB.h"


#include "ConcreateStrategyC.h"




int main()


{


 Strategy* pStrategy;




/**


 * 由于实例化不同的策略,所以最终在调用实际的算法时,所获得结果就不尽相同


 */


 pStrategy = new ConcreateStrategyA();


 Context*pContext1= new Context(pStrategy);


 pContext1->ContextInterface();




 pStrategy = new ConcreateStrategyB();


 Context*pContext2= new Context(pStrategy);


 pContext2->ContextInterface();




 pStrategy = new ConcreateStrategyC();


 Context*pContext3= new Context(pStrategy);


 pContext3->ContextInterface();




 delete pContext1;


 delete pContext2;


 delete pContext3;




 return 0;


}


六、实例UML图及源码





(1)纯策略模式

/************************************************************************


* FileName: CashSuperStratrgy.h


* Author: steven oyj (steven.oyj@gmail.com)


* Description : 抽象收费算法类:定义所有支持的收费算法的公共接口


* Time: 2010/5/24


************************************************************************/


#ifndef CASHSUPERSTRATEGY_H


#define CASHSUPERSTRATEGY_H




class CashSuperStrategy


{


public:


 CashSuperStrategy(){}


 virtual ~CashSuperStrategy(){}


 // 收费算法


 virtual double AcceptCash(double dMoney) = 0;


 protected:


private:


};




#endif // CASHSUPERSTRATEGY_H


/************************************************************************


* FileName: CashContext.h


* Author: steven oyj (steven.oyj@gmail.com)


* Description : 上下文类,用一个CashConcreateStrategy来配置,维护一个对CashSuperStratrgy对象的引用


* Time: 2010/5/24


************************************************************************/


#ifndef CASHCONTEXT_H


#define CASHCONTEXT_H


#include "CashSuperStrategy.h"


#include <iostream>




class CashContext


{


public:


 CashContext(CashSuperStrategy *pCashSuperStrategy);//构造时,传入具体的收费策略对象


 ~CashContext();




 double GetResult(double dMoney);// 根据具体的收费策略对象,获得具体的计算结果


 protected:


private:


 CashSuperStrategy* m_pCashSuperStrategy;


};




#endif // CASHCONTEXT_H


/************************************************************************


* FileName: CashContext.cpp


* Author: steven oyj (steven.oyj@gmail.com)


* Description : CashContext的具体实现


* Time: 2010/5/24


************************************************************************/


#include "CashContext.h"




CashContext::CashContext(CashSuperStrategy * pCashSuperStrategy)


{


 //ctor


 this->m_pCashSuperStrategy = pCashSuperStrategy;


}




CashContext::~CashContext()


{


 //dtor


 delete m_pCashSuperStrategy;


 m_pCashSuperStrategy = NULL;


}




double CashContext::GetResult(double dMoney)


{


 return m_pCashSuperStrategy->AcceptCash(dMoney);


}


/************************************************************************


* FileName: CashNormalStrategy.h


* Author: steven oyj (steven.oyj@gmail.com)


* Description : 具体的正常收费算法类CashNormalStrategy:封装了具体的正常收费算法,继承于Strategy


* Time: 2010/5/24


************************************************************************/


#ifndef CASHNORMALSTRATEGY_H


#define CASHNORMALSTRATEGY_H




#include "CashSuperStrategy.h"






class CashNormalStrategy : public CashSuperStrategy


{


public:


 CashNormalStrategy();


 virtual ~CashNormalStrategy();




 // 具体的收费算法


 virtual double AcceptCash(double dMoney);


 protected:


private:


};




#endif // CASHNORMALSTRATEGY_H


/************************************************************************


* FileName: CashNormalStrategy.cpp


* Author: steven oyj (steven.oyj@gmail.com)


* Description : CashNormalStrategy的具体实现


* Time: 2010/5/24


************************************************************************/


#include "CashNormalStrategy.h"




CashNormalStrategy::CashNormalStrategy()


{


 //ctor


}




CashNormalStrategy::~CashNormalStrategy()


{


 //dtor


}




double CashNormalStrategy::AcceptCash(double dMoney)


{


 return dMoney;


}


/************************************************************************


* FileName: CashRebateStrategy.h


* Author: steven oyj (steven.oyj@gmail.com)


* Description : 具体的打则收费算法类CashNormalStrategy:封装了具体的打折收费算法,继承于Strategy


* Time: 2010/5/24


************************************************************************/


#ifndef CASHREBATESTRATEGY_H


#define CASHREBATESTRATEGY_H




#include "CashSuperStrategy.h"




class CashRebateStrategy : public CashSuperStrategy


{


public:


 CashRebateStrategy(double dMoneyRebate);


 virtual ~CashRebateStrategy();




 // 具体的收费算法


 virtual double AcceptCash(double dMoney);


 protected:


private:


 double m_dMoneyRebate;


};




#endif // CASHREBATESTRATEGY_H


/************************************************************************


* FileName: CashRebateStrategy.cpp


* Author: steven oyj (steven.oyj@gmail.com)


* Description : CashRebateStrategy的具体实现


* Time: 2010/5/24


************************************************************************/


#include "CashRebateStrategy.h"




CashRebateStrategy::CashRebateStrategy(double dMoneyRebate)


{


 //ctor


 this->m_dMoneyRebate = dMoneyRebate;


}




CashRebateStrategy::~CashRebateStrategy()


{


 //dtor


}




double CashRebateStrategy::AcceptCash(double dMoney)


{


 return dMoney * m_dMoneyRebate;


}


/************************************************************************


* FileName: CashReturnStrategy.h


* Author: steven oyj (steven.oyj@gmail.com)


* Description : 具体的返现收费算法类CashReturnStrategy:封装了具体的返现收费算法,继承于Strategy


* Time: 2010/5/24


************************************************************************/


#ifndef CASHRETURNSTRATEGY_H


#define CASHRETURNSTRATEGY_H




#include "CashSuperStrategy.h"




class CashReturnStrategy : public CashSuperStrategy


{


public:


 CashReturnStrategy(double dMoneyCondition, double dMoneyReturn);


 virtual ~CashReturnStrategy();




 // 具体的收费算法


 virtual double AcceptCash(double dMoney);


 protected:


private:


 double m_dMoneyCondition;


 double m_dMoneyReturn;


};




#endif // CASHRETURNSTRATEGY_H


/************************************************************************


* FileName: CashReturnStrategy.cpp


* Author: steven oyj (steven.oyj@gmail.com)


* Description : CashReturnStrategy


* Time: 2010/5/24


************************************************************************/


#include "CashReturnStrategy.h"




CashReturnStrategy::CashReturnStrategy(double dMoneyCondition, double dMoneyReturn)


{


 //ctor


 this->m_dMoneyCondition = dMoneyCondition;


 this->m_dMoneyReturn = dMoneyReturn;


}




CashReturnStrategy::~CashReturnStrategy()


{


 //dtor


}




double CashReturnStrategy::AcceptCash(double dMoney)


{


 double result = dMoney;




 if (dMoney >= m_dMoneyCondition)


{


 result = dMoney - (int)(dMoney / m_dMoneyCondition) * m_dMoneyReturn;


}


 return result;


}


(2)策略与工厂结合

GOOD:客户端只需访问Context类,而不用知道其它任何类信息,实现了低耦合。

在上例基础上,增加一个结合了工厂模式的类

/************************************************************************


* FileName: CashContextWithFactory.h


* Author: steven oyj (steven.oyj@gmail.com)


* Description : 结合了工厂类的上下文类定义


* Time: 2010/5/24


************************************************************************/


#ifndef CASHCONTEXTWITHFACTORY_H


#define CASHCONTEXTWITHFACTORY_H


#include "CashSuperStrategy.h"


#include "CashNormalStrategy.h"


#include "CashRebateStrategy.h"


#include "CashReturnStrategy.h"


#include <iostream>




class CashContextWithFactory


{


public:


 CashContextWithFactory(int type);//构造时,传入具体的收费策略类型,构造函数中自行根据类型创建对应收费类对象


 virtual ~CashContextWithFactory();




 double GetResult(double dMoney);// 根据具体的收费策略对象,获得具体的计算结果


 protected:


private:


 CashSuperStrategy* m_pCashSuperStrategy;


};




#endif // CASHCONTEXTWITHFACTORY_H


/************************************************************************


* FileName: CashContextWithFactory.cpp


* Author: steven oyj (steven.oyj@gmail.com)


* Description : CashContextWithFactory的具体实现


* Time: 2010/5/24


************************************************************************/


#include "CashContextWithFactory.h"




//构造时,传入具体的收费策略类型,构造函数中自行根据类型创建对应收费类对象


CashContextWithFactory::CashContextWithFactory(int type)


{


 //ctor


 switch (type)


{


 case 0:


 m_pCashSuperStrategy = new CashNormalStrategy();


 break;


 case 1:


 m_pCashSuperStrategy = new CashRebateStrategy(0.8);


 break;


 case 2:


 m_pCashSuperStrategy = new CashReturnStrategy(300, 100);


 break;


 default:


 break;


}




}




CashContextWithFactory::~CashContextWithFactory()


{


 //dtor


 delete m_pCashSuperStrategy;


 m_pCashSuperStrategy = NULL;


}




double CashContextWithFactory::GetResult(double dMoney)


{


 return m_pCashSuperStrategy->AcceptCash(dMoney);


}


(3)测试代码

/************************************************************************


* FileName: main.cpp


* Author: steven oyj (steven.oyj@gmail.com)


* Description : 策略模型及其与工厂模式结合的测试主函数


* Time: 2010/5/24


************************************************************************/


#include <iostream>


#include "CashContext.h"


#include "CashNormalStrategy.h"


#include "CashRebateStrategy.h"


#include "CashReturnStrategy.h"


#include "CashContextWithFactory.h"




using namespace std;




void PureStratrgyTest();


void StrategyWithFactoryTest();




int main()


{


 PureStratrgyTest();


 StrategyWithFactoryTest();


 return 0;


}




/**


* 由于实例化不同的收费策略类对象,所以最终在调用实际的收费算法时,所获得结果就不尽相同


*/


void PureStratrgyTest()


{


 CashSuperStrategy* pStrategy;




 pStrategy = new CashNormalStrategy();


 CashContext*pContext1= new CashContext(pStrategy);


 cout << pContext1->GetResult(800) << endl;




 pStrategy = new CashRebateStrategy(0.8);


 CashContext*pContext2= new CashContext(pStrategy);


 cout << pContext2->GetResult(800) << endl;




 pStrategy = new CashReturnStrategy(300, 100);


 CashContext*pContext3= new CashContext(pStrategy);


 cout << pContext3->GetResult(800) << endl;




 delete pContext1;


 delete pContext2;


 delete pContext3;


}




/**


* 结合工厂模式,传入不同收费策略的指令参数,


* 由上下文类中的工厂自行实例化不同的收费策略类对象


* 所以最终在调用实际的收费算法时,所获得结果就不尽相同


*/


void StrategyWithFactoryTest()


{


 CashContextWithFactory* pContext1 = new CashContextWithFactory(0);


 cout << pContext1->GetResult(800) << endl;




 CashContextWithFactory* pContext2 = new CashContextWithFactory(1);


 cout << pContext2->GetResult(800) << endl;




 CashContextWithFactory* pContext3 = new CashContextWithFactory(2);


 cout << pContext3->GetResult(800) << endl;




 delete pContext1;


 delete pContext2;


 delete pContext3;


}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: