策略模式介绍
策略模式定义:
策略模式(Strategy):它定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。
策略模式结构图:
策略模式特点
意图: 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决: 在有多种算法相似的情况下,使用 if…else 所带来的复杂难以维护。
何时使用: 一个系统有许多许多类,而区分它们的只是他们直接的行为。
如何解决: 将这些算法封装成一个一个的类,任意地替换。
关键代码: 实现同一个接口 - 策略方法
优点:
- 算法可以自由切换。
- 避免使用多重条件判断。
- 扩展性良好。
缺点:
- 策略类会增多。
- 所有策略类都需要对外暴露。
使用场景:
- 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
- 一个系统需要动态地在几种算法中选择一种。
- 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
注意事项: 如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
策略模式实现
#include <iostream>
using namespace std;
// 抽象算法类
class Strategy
{
public:
virtual ~Strategy(){};
virtual void AlgorithmInterface() = 0;
};
// 具体算法A
class ConcreteStrategyA : public Strategy
{
public:
virtual ~ConcreteStrategyA() {}
void AlgorithmInterface()
{
cout << "算法A实现..." << endl;
}
};
// 具体算法B
class ConcreteStrategyB : public Strategy
{
public:
virtual ~ConcreteStrategyB() {}
void AlgorithmInterface()
{
cout << "算法B实现..." << endl;
}
};
// 具体算法C
class ConcreteStrategyC : public Strategy
{
public:
virtual ~ConcreteStrategyC() {}
void AlgorithmInterface()
{
cout << "算法C实现..." << endl;
}
};
// 上下文
class Context
{
public:
Context(Strategy* strategy) :strategy(strategy) {}
// 上下文方法 - 根据具体的策略对象调用其算法的方法
void ContextInterface()
{
strategy->AlgorithmInterface();
}
private:
Strategy* strategy;
};
int main()
{
// 实例不同的策略调用对应的接口获得不同的结果
Context contxtA(new ConcreteStrategyA());
contxtA.ContextInterface();
Context contxtB(new ConcreteStrategyB());
contxtB.ContextInterface();
Context contxtC(new ConcreteStrategyC());
contxtC.ContextInterface();
return 0;
}
运行结果:
算法A实现...
算法B实现...
算法C实现...
商场收银软件
需求: 除了正常的支付找零之外,还会有活动打折、满减返利等等优惠活动。
设计:
- ConcreteStrategyA:正常支付和找零
- ConcreteStrategyB:活动打折
- ConcreteStrategyC:满减返利
代码实现:
#include <iostream>
using namespace std;
class SellBase
{
public:
virtual double acceptCash(double cash) = 0;
};
// 原价收费
class CashNormal :public SellBase
{
public:
double acceptCash(double cash)
{
return cash;
}
};
// 打折收费
class CashRebate :public SellBase
{
double rebate;
public:
CashRebate(double n) :rebate(n) {}
double acceptCash(double cash)
{
return cash * rebate;
}
};
// 满减收费
class CashReturn :public SellBase
{
double cashreturn;
double condition;
public:
CashReturn(double ou, double co):condition(ou),cashreturn(co){}
double acceptCash(double cash)
{
return cash - (cash / condition)*cashreturn;
}
};
class SellContext
{
SellBase* sb;
public:
SellContext(int type)
{
switch (type)
{
case 1:
sb = new CashNormal; break;
case 2:
sb = new CashRebate(0.8); break;
case 3:
sb = new CashReturn(200, 50); break;
default:
cout << "此活动方式不存在!" << endl; break;
}
}
double getResult(double money)
{
return sb->acceptCash(money);
}
};
int main()
{
SellContext sc(3);
int rs = sc.getResult(600);
cout << rs << endl;
SellContext sc2(2);
int rs2 = sc2.getResult(100);
cout << rs2 << endl;
SellContext sc3(1);
int rs3 = sc3.getResult(100);
cout << rs3 << endl;
return 0;
}