策略模式(Strategy):将不同的算法封装起来,让它们之间可以相互替换。此模式变化算法,不会影响到使用算法的客户。策略模式结构图如下:
策略模式各类的模板如下:
Strategy类,定义所有支持的算法的公共接口
class Strategy
{
public:
virtual void AlgorithmInterface();
};
ConcreteStrategy,封装了具体的算法或行为,继承Strategy
//算法A类
ConcreteStrategyA:Strategy
{
public:
void AlgorithmInterface();//算法A实现方法
};
//算法B类
ConcreteStrategyB:Strategy
{
public:
void AlgorithmInterface();//算法B实现方法
};
//算法C类
ConcreteStrategyC:Strategy
{
public:
void AlgorithmInterface();//算法C实现方法
};
Context,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。
//上下文
class Context
{
public:
Strategy strategy;
//初始化时,传入具体的(A\B\C)策略对象
Context(Strategy strategy)
{
this.strategy = strategy
};
//上下文接口 该接口调用初始化传入的策略对象的算法
void ContextInterface()
{
strategy.AlgorithmInterface();
}
};
客户端代码
//实例化不同的策略,最终调用不同的算法
void main()
{
Context *context = NULL;
context = new Context (new ConcreteStrategyA);
context.ContextInterface();//调用A算法
context = new Context (new ConcreteStrategyB);
context.ContextInterface();//调用B算法
context = new Context (new ConcreteStrategyC);
context.ContextInterface();//调用C算法
}
注:上述实例化策略时,代码过于重复,复用性不好。可以结合简单工厂模式将实例对象的过程封装起来。
实现商场收银系统,商场具有促销(原价)、打折、返利(例如:满300减10)等活动。不同的活动对应着不同的收银算法。收银系统的类图如下:
CashSuper.h
//收银基类。属于策略模式:将不同算法封装成类
class CashSuper
{
public:
//算法虚函数
virtual double acceptCash(double money) { return 0.0; };
};
//促销类
class CashNormal : public CashSuper
{
public:
double acceptCash(double)override;
};
//打折类
class CashRebate :public CashSuper
{
public:
double moneyRebate;
CashRebate(double);
double acceptCash(double)override;
};
//返利类
class CashReturn :public CashSuper
{
public:
double moneyCondition = 0;
double moneyReturn = 0;
double acceptCash(double)override;
CashReturn(double, double);
};
//付款类型枚举值
enum CashType
{
Normal,
Rebate,
Return
};
//收银上下文类。属于策略模式,实例不同算法对象,调用相应的算法
class CashContext
{
private:
CashSuper *cs;
public:
CashContext(int type)//使用了简单工厂模式,封装不同收银类的实例化
{
switch (type) {
case Normal:
this->cs = new CashNormal();
break;
case Rebate:
cs = new CashRebate(0.8);
break;
case Return:
cs = new CashReturn(300, 100);
break;
}
};
double ContextInterface(double money)//调用不同收银实例的算法
{
return cs->acceptCash(money);
};
};
CashSuper.cpp
#include "CashSuper.h"
double CashNormal::acceptCash(double money)
{
return money;
}
//打折构造函数
CashRebate::CashRebate(double mr)
{
moneyRebate = mr;
}
//打折算法重载
double CashRebate::acceptCash(double money)
{
return money * moneyRebate;
}
//返利构造
CashReturn::CashReturn(double mc, double mr)
{
moneyCondition = mc;
moneyReturn = mr;
}
//返利算法重载
double CashReturn::acceptCash(double money)
{
if (money >= moneyCondition)
{
return money - (money / moneyCondition) * moneyReturn;
}
return money;
}
main.cpp
#include <iostream>
#include "CashSuper.h"
using namespace std;
int main()
{
//Normal:原价 Rebate:打8折 Return:满300减100
CashContext *csuper = new CashContext(Normal);//实例化一个普通收银对象
cout << csuper->ContextInterface(300)<<endl;//调用普通收银算法
return 0;
}
运行结果:
实例Normal对象输出:300
实例Rebate对象输出:240
实例Return对象输出:200