[大话设计模式] 第2章: 策略模式
策略模式(Strategy)
定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。根据不同的情况,创建不同的对象。对象不同类型相近,方法差别大, 尤其适合经常变动的多种不同算法。 一般用于多个类的方法名都相同,但是实现方式不同注重多个对象的相同行为:屏蔽方法名相同,算法实现细节不同之间的差异.
- 面向对象中并非类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。
- 策略模式:定义算法家族并分别封装,他们完成的工作相同,只是实现不同,可以互相替换。继承有助于析取这些算法的公共功能。此模式让算法的变化不会影响到使用算法的用户。
- 策略与工厂模式结合,使客户端需要认识的类减少,耦合度更加降低。
- 策略模式可以简化单元测试,因为每个算法可以通过自己的接口单独测试。
- 只要在不同时间内应用不同的业务规则,就可以考虑用策略模式来处理这种变化的可能性。
UML类图
- Stragegy类 :定义所有支持的算法的公共接口
- ConcreteStrategy :封装了具体的算法或行为,继承于Strategy
- Context :用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用或指针
商场促销策略举例说明
案例分析: 某商场有三种支付模式:
- 无优惠, 正常收取现金;
- 所有商品8折优惠;
- 每满300减100优惠;
要求使用策略模式, 实现上述要求.
注意: 也可以使用简单工厂模式, 简单工厂模式与策略模式的区别是: 简单工厂模式需要客户认识两个类, CashSuper和CashFactory, 而使用策略模式, 客户只需要认识一个类CashContext就可以了. 耦合性更加降低.
UML类图如下
代码如下:
#include <stdio.h>
typedef enum
{
cashNormal, // 正常收费
cashRebate, // 打8折优惠
cashReturn, // 满300减100
} CASHTYPE;
// 抽象策略类
class CashSuper
{
public:
virtual ~CashSuper(){ };
virtual double accept_cash(double money) = 0;
};
// 正常收费
class CashNormal : public CashSuper
{
public:
CashNormal(){ };
double accept_cash(double money){
return money;
}
};
// 打8折优惠
class CashRebate : public CashSuper
{
public:
CashRebate(double rebate_) : rebate(rebate_) { };
double accept_cash(double money){
return money * rebate;
}
private:
double rebate;
};
// 满300减100
class CashReturn : public CashSuper
{
public:
CashReturn(double con, double ret) : money_condition(con), money_return(ret){ };
double accept_cash(double money){
if(money > money_condition)
return money - (int)(money / money_condition) * money_return;
return money;
}
private:
double money_condition;
double money_return;
};
class CashContext
{
public:
CashContext(CASHTYPE type);
~CashContext();
double get_result(double money);
private:
CashSuper *c_super;
};
CashContext::CashContext(CASHTYPE type)
{
switch(type) // 根据商场优惠类型不同, 创建不同对象, 类似简单工厂模式
{
case cashNormal:
c_super = new CashNormal(); break;
case cashRebate:
c_super = new CashRebate(0.8); break;
case cashReturn:
c_super = new CashReturn(300, 100); break;
default:
c_super = NULL;
}
}
CashContext::~CashContext()
{
delete c_super;
}
double CashContext::get_result(double money)
{
return c_super->accept_cash(money);
}
int main()
{
double pay = 600;
CashContext *cc = new CashContext(cashNormal); // 正常收费
printf("支付现金%f, 实际收现金 %f\n", pay, cc->get_result(pay));
cc = new CashContext(cashRebate); // 8折
printf("支付现金%f, 实际收现金 %f\n", pay, cc->get_result(pay));
cc = new CashContext(cashReturn); // 满300减100
printf("支付现金%f, 实际收现金 %f\n", pay, cc->get_result(pay));
delete cc;
return 0;
}
/* 输出结果
支付现金600.000000, 实际收现金 600.000000
支付现金600.000000, 实际收现金 480.000000
支付现金600.000000, 实际收现金 400.000000
*/
参考链接
大话设计模式C++源码: https://github.com/yogykwan/design-patterns-cpp
http://www.cnblogs.com/moon1992/