Linux C++ 046-设计模式之策略模式
本节关键字:Linux、C++、设计模式、策略模式
相关库函数:
概念
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。(原文:The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.)
Context(应用场景):
1、需要使用ConcreteStrategy提供的算法。
2、 内部维护一个Strategy的实例。
3、 负责动态设置运行时Strategy具体的实现算法。
4、负责跟Strategy之间的交互和数据传递。
Strategy(抽象策略类):
1、 定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,Context使用这个接口调用不同的算法,一般使用接口或 抽象类实现。
ConcreteStrategy(具体策略类):
1、 实现了Strategy定义的接口,提供具体的算法实现。
应用场景
1、 多个类只区别在 表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。(例如FlyBehavior和QuackBehavior)
2、 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。(例如FlyBehavior和QuackBehavior的具体实现可任意变化或扩充)
3、 对客户(Duck)隐藏具体策略(算法)的实现细节,彼此完全独立。
优缺点
优点:
1、 提供了一种替代继承的方法,而且既保持了继承的优点(代码重用)还比继承更灵活(算法独立,可以任意扩展)。
2、 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
3、 遵守大部分GRASP原则和常用设计原则, 高内聚、低偶合。
缺点:
1、 因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。
代码示例
class CashSuper
{
public:
virtual double acceptMoney(double money) = 0;
};
// 策略类1
class CashNormal : public CashSuper
{
public:
double acceptMoney(double money) {
return money;
}
};
// 策略类2
class CashRebate : public CashSuper
{
private:
double discount;
public:
CashRebate(double dis) {
discount = dis;
}
double acceptMoney(double money) {
return money * discount;
}
};
// 策略类3
class CashReturn : public CashSuper
{
private:
double moneyCondition;
double moneyReturn;
public:
CashReturn(double mc, double mr) {
moneyCondition = mc;
moneyReturn = mr;
}
double accoptMoney(double money) {
double result = money;
if (money >= moneyCondition) {
result = money - floor(money / moneyCondition) * moneyReturn;
}
return result;
}
};
// 上下文
class CashContext
{
private:
CashSuper* cs;
public:
CashContext(CashSuper* cs) { // 维护一个对策略对象的引用
this->cs = cs;
}
double getResult(double money) { // 调用相应的算法
return cs->acceptMoney(money);
}
};
// 上述代码中相当于定义了3种策略,从策略基类派生出3种策略派生类
// 上下文类:定义了一个策略基类类型的成员变量,定义了调用策略派生类种算法的成员函数
// 客户端:需要知道上下文类和策略类,创建策略对象,借助上下文对象调用不同的算法
int main_Cash()
{
CashSuper* cs;
CashContext* cc;
double money;
money = 1000;
cs = new CashRebate(0.8);
cc = new CashContext(cs);
cout << cc->getResult(money) << endl;
money = 1000;
cs = new CashNormal();
cc = new CashContext(cs);
cout << cc->getResult(money) << endl;
return 0;
}
策略模式和简单工厂模式组合
// 策略模式和简单工厂模式相结合
// 优点:客户端只需访问上下文类,而不需要知道其他的信息,实现了低耦合
#include <cmath>
class CashSuper2
{
public:
virtual double acceptMoney(double money) = 0;
};
// 策略类1
class CashNormal2 : public CashSuper2
{
public:
double acceptMoney(double money) {
return money;
}
};
// 策略类2
class CashRebate2 : public CashSuper2
{
private:
double discount;
public:
CashRebate2(double dis) {
discount = dis;
}
double acceptMoney(double money) {
return money * discount;
}
};
// 策略类3
class CashReturn2 : public CashSuper2
{
private:
double moneyCondition;
double moneyReturn;
public:
CashReturn2(double mc, double mr) {
moneyCondition = mc;
moneyReturn = mr;
}
double acceptMoney(double money) {
double result = money;
if (money >= moneyCondition) {
result = money - floor(money / moneyCondition) * moneyReturn;
}
return result;
}
};
// 上下文
class CashContext2
{
private:
CashSuper2* cs;
public:
CashContext2(string str) {
if (str == "正常收费") {
cs = new CashNormal2();
}
else if (str == "打9折") {
cs = new CashRebate2(0.9);
}
else if (str == "满300送200") {
cs = new CashReturn2(300, 200);
}
else {
cs = NULL;
}
}
double getResult(double money) { // 调用相应的算法
return cs->acceptMoney(money);
}
};
// 策略派生类和策略模式的相同,有一个策略基类,派生了3个策略类。区别在于上下文类
// 上下文类:定义了一个策略基类的对象,在策略基类的对象中来决定实例化哪种策略对象(区别于策略模式),定义一个成员函数,调用策略中定义个算法
// 客户端:自需要知晓上下文类即可。只需创建上下文类的对象,调用该类中的方法即可获得结果
int main_FectoryAndCash()
{
double money = 1000;
CashContext2* cc = new CashContext2("打9折");
cout << cc->getResult(money) << endl;
return 0;
}