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

一、意图

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

二、基本思想

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

三、优缺点分析

GOOD:

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

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

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

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

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

四、适用情况

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

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

五、标准UML图例及源码

(1)标准UML图列

(V2Z$)ZJUDX~D)Z$}{U$}(F

(2)标准源码

   1: /************************************************************************
   2:  * FileName    : Strategy.h
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : 抽象算法类:定义所有支持的算法的公共接口
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #ifndef STRATEGY_H
   8: #define STRATEGY_H
   9:  
  10: class Strategy
  11: {
  12: public:
  13:     virtual ~Strategy(){}
  14:     // 算法方法
  15:     virtual void AlgorithmInterface() = 0;
  16: };
  17: #endif
   1: /************************************************************************
   2:  * FileName    : Context.h
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : 上下文类,用一个ConcreateStrategy来配置,维护一个对Strategy对象的引用
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #ifndef CONTEXT_H
   8: #define CONTEXT_H
   9:  
  10: #include "Strategy.h"
  11: #include <iostream>
  12:  
  13: class Context
  14: {
  15: public:
  16:     Context(Strategy *pStrategy);// 构造时,传入具体的策略对象
  17:     ~Context();
  18:  
  19:     void ContextInterface();// 根据具体的策略对象,调用其算法的方法
  20: private:
  21:     Strategy* m_pStrategy;
  22: };
  23:  
  24: #endif // CONTEXT_H

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

   2:  * FileName    : ConcreateStrategyA.h
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : 具体算法类A:封装了具体的算法或行为,继承于Strategy
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #ifndef CONCREATESTRATEGYA_H
   8: #define CONCREATESTRATEGYA_H
   9:  
  10: #include "Strategy.h"
  11: #include <iostream>
  12:  
  13: class ConcreateStrategyA
  14:     : public Strategy
  15: {
  16: public:
  17:     virtual ~ConcreateStrategyA(){}
  18:     // 算法A实现方法
  19:     virtual void AlgorithmInterface();
  20: };
  21:  
  22: #endif // CONCREATESTRATEGYA_H
   1: /************************************************************************
   2:  * FileName    : ConcreateStrategyB.h
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : 具体算法类B:封装了具体的算法或行为,继承于Strategy
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #ifndef CONCREATESTRATEGYB_H
   8: #define CONCREATESTRATEGYB_H
   9:  
  10: #include "Strategy.h"
  11: #include <iostream>
  12:  
  13: class ConcreateStrategyB
  14:     : public Strategy
  15: {
  16: public:
  17:     virtual ~ConcreateStrategyB(){}
  18:     // 算法B实现方法
  19:     virtual void AlgorithmInterface();
  20: };
  21:  
  22: #endif // CONCREATESTRATEGYB_H
   1: /************************************************************************
   2:  * FileName    : ConcreateStrategyC.h
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : 具体算法C:封装了具体的算法或行为,继承于Strategy
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #ifndef CONCREATESTRATEGYC_H
   8: #define CONCREATESTRATEGYC_H
   9:  
  10: #include "Strategy.h"
  11: #include <iostream>
  12:  
  13: class ConcreateStrategyC
  14:     : public Strategy
  15: {
  16: public:
  17:     virtual ~ConcreateStrategyC(){}
  18:     // 算法C实现方法
  19:     virtual void AlgorithmInterface();
  20: };
  21:  
  22: #endif // CONCREATESTRATEGYC_H
   1: /************************************************************************
   2:  * FileName    : Context.cpp
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : 上下文类的具体实现
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #include "Context.h"
   8:  
   9: // 构造时,传入具体的策略对象
  10: Context::Context(Strategy *pStrategy)
  11:     : m_pStrategy(pStrategy)
  12: {
  13: }
  14:  
  15: Context::~Context()
  16: {
  17:     delete m_pStrategy;
  18:     m_pStrategy = NULL;
  19: }
  20:  
  21: // 根据具体的策略对象,调用其算法的方法
  22: void Context::ContextInterface()
  23: {
  24:     if (NULL != m_pStrategy)
  25:     {
  26:         m_pStrategy->AlgorithmInterface();
  27:     }
  28: }
   1: /************************************************************************
   2:  * FileName    : ConcreateStrategyA.cpp
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : ConcreateStrategyA类的具体实现
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #include "ConcreateStrategyA.h"
   8:  
   9: // 算法A实现方法
  10: void ConcreateStrategyA::AlgorithmInterface()
  11: {
  12:     std::cout << "AlgorithmInterface Implemented by ConcreateStrategyA\n";
  13: }
   1: /************************************************************************
   2:  * FileName    : ConcreateStrategyC.cpp
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : ConcreateStrategyC类的具体实现
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #include "ConcreateStrategyC.h"
   8:  
   9: // 算法C实现方法
  10: void ConcreateStrategyC::AlgorithmInterface()
  11: {
  12:     std::cout << "AlgorithmInterface Implemented by ConcreateStrategyC\n";
  13: }
   1: /************************************************************************
   2:  * FileName    : ConcreateStrategyB.cpp
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : ConcreateStrategyB类的具体实现
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #include "ConcreateStrategyB.h"
   8:  
   9: // 算法B实现方法
  10: void ConcreateStrategyB::AlgorithmInterface()
  11: {
  12:     std::cout << "AlgorithmInterface Implemented by ConcreateStrategyB\n";
  13: }
   1: /************************************************************************
   2:  * FileName    : Main.cpp
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : Strategy模式的测试代码
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #include "Context.h"
   8: #include "ConcreateStrategyA.h"
   9: #include "ConcreateStrategyB.h"
  10: #include "ConcreateStrategyC.h"
  11:  
  12: int main()
  13: {
  14:     Strategy* pStrategy;
  15:  
  16:     /**
  17:     * 由于实例化不同的策略,所以最终在调用实际的算法时,所获得结果就不尽相同
  18:     */
  19:     pStrategy = new ConcreateStrategyA();
  20:     Context*  pContext1  = new Context(pStrategy);
  21:     pContext1->ContextInterface();
  22:  
  23:     pStrategy = new ConcreateStrategyB();
  24:     Context*  pContext2  = new Context(pStrategy);
  25:     pContext2->ContextInterface();
  26:  
  27:     pStrategy = new ConcreateStrategyC();
  28:     Context*  pContext3  = new Context(pStrategy);
  29:     pContext3->ContextInterface();
  30:  
  31:     delete pContext1;
  32:     delete pContext2;
  33:     delete pContext3;
  34:  
  35:     return 0;
  36: }

六、实例UML图及源码

clip_image002

(1)纯策略模式

   1: /************************************************************************
   2:  * FileName    : CashSuperStratrgy.h
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : 抽象收费算法类:定义所有支持的收费算法的公共接口
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #ifndef CASHSUPERSTRATEGY_H
   8: #define CASHSUPERSTRATEGY_H
   9:  
  10: class CashSuperStrategy
  11: {
  12:     public:
  13:         CashSuperStrategy() {}
  14:         virtual ~CashSuperStrategy() {}
  15:         // 收费算法
  16:         virtual double AcceptCash(double dMoney) = 0;
  17:     protected:
  18:     private:
  19: };
  20:  
  21: #endif // CASHSUPERSTRATEGY_H
   1: /************************************************************************
   2:  * FileName    : CashContext.h
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : 上下文类,用一个CashConcreateStrategy来配置,维护一个对CashSuperStratrgy对象的引用
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #ifndef CASHCONTEXT_H
   8: #define CASHCONTEXT_H
   9: #include "CashSuperStrategy.h"
  10: #include <iostream>
  11:  
  12: class CashContext
  13: {
  14:     public:
  15:         CashContext(CashSuperStrategy *pCashSuperStrategy);//构造时,传入具体的收费策略对象
  16:         ~CashContext();
  17:  
  18:         double GetResult(double dMoney);// 根据具体的收费策略对象,获得具体的计算结果
  19:     protected:
  20:     private:
  21:         CashSuperStrategy* m_pCashSuperStrategy;
  22: };
  23:  
  24: #endif // CASHCONTEXT_H
   1: /************************************************************************
   2:  * FileName    : CashContext.cpp
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : CashContext的具体实现
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #include "CashContext.h"
   8:  
   9: CashContext::CashContext(CashSuperStrategy * pCashSuperStrategy)
  10: {
  11:     //ctor
  12:     this->m_pCashSuperStrategy = pCashSuperStrategy;
  13: }
  14:  
  15: CashContext::~CashContext()
  16: {
  17:     //dtor
  18:     delete m_pCashSuperStrategy;
  19:     m_pCashSuperStrategy = NULL;
  20: }
  21:  
  22: double CashContext::GetResult(double dMoney)
  23: {
  24:     return m_pCashSuperStrategy->AcceptCash(dMoney);
  25: }
   1: /************************************************************************
   2:  * FileName    : CashNormalStrategy.h
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : 具体的正常收费算法类CashNormalStrategy:封装了具体的正常收费算法,继承于Strategy
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #ifndef CASHNORMALSTRATEGY_H
   8: #define CASHNORMALSTRATEGY_H
   9:  
  10: #include "CashSuperStrategy.h"
  11:  
  12:  
  13: class CashNormalStrategy : public CashSuperStrategy
  14: {
  15:     public:
  16:         CashNormalStrategy();
  17:         virtual ~CashNormalStrategy();
  18:  
  19:         // 具体的收费算法
  20:         virtual double AcceptCash(double dMoney);
  21:     protected:
  22:     private:
  23: };
  24:  
  25: #endif // CASHNORMALSTRATEGY_H
   1: /************************************************************************
   2:  * FileName    : CashNormalStrategy.cpp
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : CashNormalStrategy的具体实现
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #include "CashNormalStrategy.h"
   8:  
   9: CashNormalStrategy::CashNormalStrategy()
  10: {
  11:     //ctor
  12: }
  13:  
  14: CashNormalStrategy::~CashNormalStrategy()
  15: {
  16:     //dtor
  17: }
  18:  
  19: double CashNormalStrategy::AcceptCash(double dMoney)
  20: {
  21:     return dMoney;
  22: }
   1: /************************************************************************
   2:  * FileName    : CashRebateStrategy.h
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : 具体的打则收费算法类CashNormalStrategy:封装了具体的打折收费算法,继承于Strategy
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #ifndef CASHREBATESTRATEGY_H
   8: #define CASHREBATESTRATEGY_H
   9:  
  10: #include "CashSuperStrategy.h"
  11:  
  12: class CashRebateStrategy : public CashSuperStrategy
  13: {
  14:     public:
  15:         CashRebateStrategy(double dMoneyRebate);
  16:         virtual ~CashRebateStrategy();
  17:  
  18:         // 具体的收费算法
  19:         virtual double AcceptCash(double dMoney);
  20:     protected:
  21:     private:
  22:         double m_dMoneyRebate;
  23: };
  24:  
  25: #endif // CASHREBATESTRATEGY_H
   1: /************************************************************************
   2:  * FileName    : CashRebateStrategy.cpp
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : CashRebateStrategy的具体实现
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #include "CashRebateStrategy.h"
   8:  
   9: CashRebateStrategy::CashRebateStrategy(double dMoneyRebate)
  10: {
  11:     //ctor
  12:     this->m_dMoneyRebate = dMoneyRebate;
  13: }
  14:  
  15: CashRebateStrategy::~CashRebateStrategy()
  16: {
  17:     //dtor
  18: }
  19:  
  20: double CashRebateStrategy::AcceptCash(double dMoney)
  21: {
  22:     return dMoney * m_dMoneyRebate;
  23: }
   1: /************************************************************************
   2:  * FileName    : CashReturnStrategy.h
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : 具体的返现收费算法类CashReturnStrategy:封装了具体的返现收费算法,继承于Strategy
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #ifndef CASHRETURNSTRATEGY_H
   8: #define CASHRETURNSTRATEGY_H
   9:  
  10: #include "CashSuperStrategy.h"
  11:  
  12: class CashReturnStrategy : public CashSuperStrategy
  13: {
  14:     public:
  15:         CashReturnStrategy(double dMoneyCondition, double dMoneyReturn);
  16:         virtual ~CashReturnStrategy();
  17:  
  18:         // 具体的收费算法
  19:         virtual double AcceptCash(double dMoney);
  20:     protected:
  21:     private:
  22:         double m_dMoneyCondition;
  23:         double m_dMoneyReturn;
  24: };
  25:  
  26: #endif // CASHRETURNSTRATEGY_H
   1: /************************************************************************
   2:  * FileName    : CashReturnStrategy.cpp
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : CashReturnStrategy
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #include "CashReturnStrategy.h"
   8:  
   9: CashReturnStrategy::CashReturnStrategy(double dMoneyCondition, double dMoneyReturn)
  10: {
  11:     //ctor
  12:     this->m_dMoneyCondition = dMoneyCondition;
  13:     this->m_dMoneyReturn = dMoneyReturn;
  14: }
  15:  
  16: CashReturnStrategy::~CashReturnStrategy()
  17: {
  18:     //dtor
  19: }
  20:  
  21: double CashReturnStrategy::AcceptCash(double dMoney)
  22: {
  23:     double result = dMoney;
  24:  
  25:     if (dMoney >= m_dMoneyCondition)
  26:     {
  27:         result = dMoney - (int)(dMoney / m_dMoneyCondition) * m_dMoneyReturn;
  28:     }
  29:     return result;
  30: }

(2)策略与工厂结合

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

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

   1: /************************************************************************
   2:  * FileName    : CashContextWithFactory.h
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : 结合了工厂类的上下文类定义
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #ifndef CASHCONTEXTWITHFACTORY_H
   8: #define CASHCONTEXTWITHFACTORY_H
   9: #include "CashSuperStrategy.h"
  10: #include "CashNormalStrategy.h"
  11: #include "CashRebateStrategy.h"
  12: #include "CashReturnStrategy.h"
  13: #include <iostream>
  14:  
  15: class CashContextWithFactory
  16: {
  17:     public:
  18:         CashContextWithFactory(int type);//构造时,传入具体的收费策略类型,构造函数中自行根据类型创建对应收费类对象
  19:         virtual ~CashContextWithFactory();
  20:  
  21:         double GetResult(double dMoney);// 根据具体的收费策略对象,获得具体的计算结果
  22:     protected:
  23:     private:
  24:         CashSuperStrategy* m_pCashSuperStrategy;
  25: };
  26:  
  27: #endif // CASHCONTEXTWITHFACTORY_H
   1: /************************************************************************
   2:  * FileName    : CashContextWithFactory.cpp
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : CashContextWithFactory的具体实现
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #include "CashContextWithFactory.h"
   8:  
   9: //构造时,传入具体的收费策略类型,构造函数中自行根据类型创建对应收费类对象
  10: CashContextWithFactory::CashContextWithFactory(int type)
  11: {
  12:     //ctor
  13:     switch (type)
  14:     {
  15:         case 0:
  16:             m_pCashSuperStrategy = new CashNormalStrategy();
  17:             break;
  18:         case 1:
  19:             m_pCashSuperStrategy = new CashRebateStrategy(0.8);
  20:             break;
  21:         case 2:
  22:             m_pCashSuperStrategy = new CashReturnStrategy(300, 100);
  23:             break;
  24:         default:
  25:             break;
  26:     }
  27:  
  28: }
  29:  
  30: CashContextWithFactory::~CashContextWithFactory()
  31: {
  32:     //dtor
  33:     delete m_pCashSuperStrategy;
  34:     m_pCashSuperStrategy = NULL;
  35: }
  36:  
  37: double CashContextWithFactory::GetResult(double dMoney)
  38: {
  39:     return m_pCashSuperStrategy->AcceptCash(dMoney);
  40: }

(3)测试代码

   1: /************************************************************************
   2:  * FileName    : main.cpp
   3:  * Author      : steven oyj (steven.oyj@gmail.com)
   4:  * Description : 策略模型及其与工厂模式结合的测试主函数
   5:  * Time        : 2010/5/24
   6:  ************************************************************************/
   7: #include <iostream>
   8: #include "CashContext.h"
   9: #include "CashNormalStrategy.h"
  10: #include "CashRebateStrategy.h"
  11: #include "CashReturnStrategy.h"
  12: #include "CashContextWithFactory.h"
  13:  
  14: using namespace std;
  15:  
  16: void PureStratrgyTest();
  17: void StrategyWithFactoryTest();
  18:  
  19: int main()
  20: {
  21:     PureStratrgyTest();
  22:     StrategyWithFactoryTest();
  23:     return 0;
  24: }
  25:  
  26: /**
  27:  * 由于实例化不同的收费策略类对象,所以最终在调用实际的收费算法时,所获得结果就不尽相同
  28:  */
  29: void PureStratrgyTest()
  30: {
  31:     CashSuperStrategy* pStrategy;
  32:  
  33:     pStrategy = new CashNormalStrategy();
  34:     CashContext*  pContext1  = new CashContext(pStrategy);
  35:     cout << pContext1->GetResult(800) << endl;
  36:  
  37:     pStrategy = new CashRebateStrategy(0.8);
  38:     CashContext*  pContext2  = new CashContext(pStrategy);
  39:     cout << pContext2->GetResult(800) << endl;
  40:  
  41:     pStrategy = new CashReturnStrategy(300, 100);
  42:     CashContext*  pContext3  = new CashContext(pStrategy);
  43:     cout << pContext3->GetResult(800) << endl;
  44:  
  45:     delete pContext1;
  46:     delete pContext2;
  47:     delete pContext3;
  48: }
  49:  
  50: /**
  51:  * 结合工厂模式,传入不同收费策略的指令参数,
  52:  * 由上下文类中的工厂自行实例化不同的收费策略类对象
  53:  * 所以最终在调用实际的收费算法时,所获得结果就不尽相同
  54:  */
  55: void StrategyWithFactoryTest()
  56: {
  57:     CashContextWithFactory* pContext1 = new CashContextWithFactory(0);
  58:     cout << pContext1->GetResult(800) << endl;
  59:  
  60:     CashContextWithFactory* pContext2 = new CashContextWithFactory(1);
  61:     cout << pContext2->GetResult(800) << endl;
  62:  
  63:     CashContextWithFactory* pContext3 = new CashContextWithFactory(2);
  64:     cout << pContext3->GetResult(800) << endl;
  65:  
  66:     delete pContext1;
  67:     delete pContext2;
  68:     delete pContext3;
  69: }
posted @ 2011-05-17 12:26  红脸书生  阅读(841)  评论(0编辑  收藏  举报