[大话设计模式] 第2章: 策略模式

策略模式(Strategy)

定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。根据不同的情况,创建不同的对象。对象不同类型相近,方法差别大, 尤其适合经常变动的多种不同算法。 一般用于多个类的方法名都相同,但是实现方式不同注重多个对象的相同行为:屏蔽方法名相同,算法实现细节不同之间的差异.

  • 面向对象中并非类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。
  • 策略模式:定义算法家族并分别封装,他们完成的工作相同,只是实现不同,可以互相替换。继承有助于析取这些算法的公共功能。此模式让算法的变化不会影响到使用算法的用户。
  • 策略与工厂模式结合,使客户端需要认识的类减少,耦合度更加降低。
  • 策略模式可以简化单元测试,因为每个算法可以通过自己的接口单独测试。
  • 只要在不同时间内应用不同的业务规则,就可以考虑用策略模式来处理这种变化的可能性。

UML类图

  • Stragegy类 :定义所有支持的算法的公共接口
  • ConcreteStrategy :封装了具体的算法或行为,继承于Strategy
  • Context :用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用或指针

商场促销策略举例说明

案例分析: 某商场有三种支付模式:

  1. 无优惠, 正常收取现金;
  2. 所有商品8折优惠;
  3. 每满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

posted @ 2017-08-01 11:31  moon1992  阅读(396)  评论(0编辑  收藏  举报