行为型模式:Strategy——策略模式
一、意图
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换,本模式使得算法可独立于使用它的客户而变化——四人团
二、基本思想
定义算法家族,分别封装起来,让它们之间可以互相替换,让算法的变化,不会影响到使用算法的用户。
三、优缺点分析
GOOD:
(1)策略模式是一种定义一系列算法的方法,从概念上看,所有这些算法完成的都是相同的工作,只是实现不同。
所以使用策略模式,就可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。
(2)策略模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能
(3)简化了单元测试(因为每个算法都有自己的类,可以通过自己的接口单独测试)
BUG:客户端要做出判断使用哪个具体算法(可通过在context中与工厂模式的结合来消除这个问题,虽然当新增加需求时,还是要改context中的代码,但是任何需求的变更本身就是需要成本的)
四、适用情况
策略模式和简单工厂基本相同,但简单工厂模式只能解决对象创建问题,对于类中的成员以方法为主,而且算法经常变动的类,应使用策略模式。
在实践中,策略模式实际上可以封装几乎任何类型的规则,只要在分析过程中听到需要不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。
五、标准UML图例及源码
(1)标准UML图列
(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图及源码
(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: }