首页 > 技术文章 > 设计模式(2)--策略模式

sylar-liang 2016-11-01 01:17 原文

//2.策略模式
//ver1
//现金收费抽象类
class CashSuper
{
public:
	CashSuper(){}
	~CashSuper(){}
public:
	virtual double acceptCash(double money)
	{
		return money;
	}
};

//正常收费类
class CashNormal : public CashSuper
{
public:
	CashNormal(){}
	~CashNormal(){}
public:
	virtual double acceptCash(double money)
	{
		return money;
	}
};

//打折收费类
class CashRebate : public CashSuper
{
private:
	double _moneyRebate;

public:
	CashRebate(double moneyRebate)
	{
		_moneyRebate = moneyRebate;
	}

	virtual double acceptCash(double money)
	{
		return money * _moneyRebate;
	}
};

//返利收费类
class CashReturn : public CashSuper
{
private:
	double _moneyCondition;
	double _moneyReturn;
public:
	CashReturn(double moneyCondition, double moneyReturn)
	{
		_moneyCondition = moneyCondition;
		_moneyReturn = moneyReturn;
	}
	virtual double acceptCash(double money)
	{
		double result = money;
		if (money >= _moneyCondition)
		{
			money = money - floor(money/_moneyCondition) * _moneyReturn; //floor 向下取整; ceil 向上取整
		}
		return money;
	}
};

enum eCashType
{
	eNormal = 1,
	eRebate = 2,
	eReturn = 3
};	


//现金收费工厂类
class CashFactory
{
public:
	static CashSuper CreateCashAccept(eCashType eType)
	{
		CashSuper * cs = NULL;
		switch(eType)
		{
		case eNormal:
			cs = new CashNormal();
			break;
		case eRebate:
			cs = new CashRebate(0.8);
			break;
		case eReturn:
			cs =new CashReturn(300, 100);
			break;
		default:
			break;
		}
		return *cs;
	}
};

void main1()
{
	double total = 0.0;
	CashSuper csuper = CashFactory::CreateCashAccept(eRebate);
	total = csuper.acceptCash(350); 
	//这里不方便在于,没法控制多少折; 参数没法传入;
	//解决:这里的处理是在定义枚举时分别定义,比如定八折 eRebate8 ,5折 eRebate5; 增加对应 case 语句;

	//缺点: 工厂包含了所有的收费方式,每增加一种或者修改一种收费方式,都需要更改工厂内容;
}

 

策略模式: 定义算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到算法的客户.

//2.策略模式
//抽象算法类
class Strategy
{
public:
	virtual void AlgorithmInterface() = 0;
};

//具体算法A
class ConcreteStrategyA : public Strategy
{
public:
	virtual void AlgorithmInterface()
	{
		//算法A
	}
};

//具体算法B
class ConcreteStrategyB : public Strategy
{
public:
	virtual void AlgorithmInterface()
	{
		//算法B
	}
};

//上下文; 用于管理 Strategy
class Context
{
private:
	Strategy * _strategy;

public:
	Context(Strategy * strategy)
	{
		_strategy = strategy;
	}

	//上下文接口
	void ContextInterface()
	{
		_strategy->AlgorithmInterface();
	}
};

void main21()
{
	Context *pContext = new Context(new ConcreteStrategyA());
	pContext->ContextInterface();

	pContext = new Context(new ConcreteStrategyB());
	pContext->ContextInterface();
}

//2.策略模式
//ver2
//现金收费抽象类
class CashSuper
{
public:
	CashSuper(){}
	~CashSuper(){}
public:
	virtual double acceptCash(double money)
	{
		return money;
	}
};

//正常收费类
class CashNormal : public CashSuper
{
public:
	CashNormal(){}
	~CashNormal(){}
public:
	virtual double acceptCash(double money)
	{
		return money;
	}
};

//打折收费类
class CashRebate : public CashSuper
{
private:
	double _moneyRebate;

public:
	CashRebate(double moneyRebate)
	{
		_moneyRebate = moneyRebate;
	}

	virtual double acceptCash(double money)
	{
		return money * _moneyRebate;
	}
};

//返利收费类
class CashReturn : public CashSuper
{
private:
	double _moneyCondition;
	double _moneyReturn;
public:
	CashReturn(double moneyCondition, double moneyReturn)
	{
		_moneyCondition = moneyCondition;
		_moneyReturn = moneyReturn;
	}
	virtual double acceptCash(double money)
	{
		double result = money;
		if (money >= _moneyCondition)
		{
			money = money - floor(money/_moneyCondition) * _moneyReturn; //floor 向下取整; ceil 向上取整
		}
		return money;
	}
};

enum eCashType
{
	eNormal = 1,
	eRebate = 2,
	eReturn = 3
};	

class CashContext
{
private:
	CashSuper _csuper;
public:
	CashContext(CashSuper cs)
	{
		_csuper = cs;
	}
	double GetResult(double money)
	{
		return _csuper.acceptCash(money);
	}
};

//客户端调用
void main22()
{
	CashContext *pcc = NULL;
	CashSuper *pcs = NULL;
	eCashType eType = eRebate;
	switch(eType)
	{
	case eNormal:
		pcs = new CashNormal();
		*pcc = CashContext(*pcs);
		break;
	case eRebate:
		pcs = new CashRebate(0.8);
		*pcc = CashContext(*pcs);
	case eReturn:
		pcs = new CashReturn(300, 100);
		*pcc = CashContext(*pcs);
	default:
		break;
	}

	double money = 350;
	double result = pcc->GetResult(money);
	//缺点: 判断过程放在了客户端,暴露了太多的细节;
}

 

//3.策略模式
//ver3
//跟前面的ver2一致,只修改main和CashContext类;
class CashContext
{
private:
	CashSuper * pcs;
public:
	CashContext(eCashType eType)
	{
		switch(eType)
		{
		case eNormal:
			pcs = new CashNormal();
			break;
		case eRebate:
			pcs = new CashRebate(0.8);
			break;
		case eReturn:
			pcs = new CashReturn(300, 100);
			break;
		default:
			break;
		}
	}

	double GetResult(double money)
	{
		return pcs->acceptCash(money);
	}
};

void main31()
{
	CashContext *pcs = new CashContext(eRebate);
	double total = pcs->GetResult(350);
	//对比ver2,简单工厂模式客户端调用需要知道 CashSuper 和 CashFactory 类;
	//ver3, 简单工厂+策略模式,客户端只需要知道 CashContext 类:
}
//策略模式的Strategy类为Context定义了一系列的可供重用的算法或行为。继承有助于取出这些算法中的公共功能。
//策略模式的优点是简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。

//另一种更好的模式可能是 反射模式。  

 

  

 

推荐阅读