zoukankan      html  css  js  c++  java
  • 行为型模式: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: }
  • 相关阅读:
    【leetcode】Linked List Cycle
    wordnet的一些入门性介绍
    Wordnet的一些简单使用
    第九章:图论和网络爬虫
    自动文档摘要技术简介
    20169202 2016-2017-2《TCP/IP协议攻击》实验总结--十一周
    20169202 2016-2017-2《移动平台》第十一周学习总结
    20169202 2016-2017-2《网络攻防》第十一周学习总结
    20169202 2016-2017-2《移动平台》第十周实验总结
    20169202 2016-2017-2《网络攻防》第十周云班课实验总结
  • 原文地址:https://www.cnblogs.com/steven_oyj/p/1742999.html
Copyright © 2011-2022 走看看