設計模式(2)--策略模式

//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定義了一系列的可供重用的算法或行爲。繼承有助於取出這些算法中的公共功能。
//策略模式的優勢是簡化了單元測試,由於每一個算法都有本身的類,能夠經過本身的接口單獨測試。

//另外一種更好的模式多是 反射模式。  單元測試

相關文章
相關標籤/搜索