1. 程式人生 > >設計模式實現(二)---策略模式、策略模式與簡單工廠模式結合使用

設計模式實現(二)---策略模式、策略模式與簡單工廠模式結合使用

策略模式(Strategy): 它定義了演算法家族,分別封裝起來,讓它們之間可以互相替換,此模式讓演算法的變化,不會影響到使用演算法的使用者。


策略模式大致實現方法

#include <stdio.h>
//抽象演算法類
class Strategy
{
public:
	virtual void AlgorithmInterface() = 0;
};

//具體演算法A
class ConcreteStragtegyA : public Strategy
{
public:
	void AlgorithmInterface()
	{
		printf("方法 A 實現 \n");
	}
};

//具體演算法B
class ConcreteStragtegyB : public Strategy
{
public:
	void AlgorithmInterface()
	{
		printf("方法 B 實現 \n");
	}
};

//具體演算法C
class ConcreteStragtegyC : public Strategy
{
public:
	void AlgorithmInterface()
	{
		printf("方法 C 實現 \n");
	}
};

//上下文
class Context
{
public:
	//初始化的時候傳入具體策略的引用
	Context(Strategy &str) : strategy(str){}	//引用必須在引數初始化列表中初始化
public:
	//根據具體的策略呼叫具體的方法
	void ContextInterface()
	{
		strategy.AlgorithmInterface();
	}
private:
	Strategy &strategy;	//此處可以用引用,也可以用指標。
};
int main()
{
	//Context *context = new Context(*(new ConcreteStragtegyA()));
	//context->ContextInterface();
	//delete context;
	//context = new Context(*(new ConcreteStragtegyB()));
	//context->ContextInterface();
	//delete context;
	//context = new Context(*(new ConcreteStragtegyC()));
	//context->ContextInterface();
	//delete context;
	ConcreteStragtegyA stragtegyA;
	Context context(stragtegyA);
	context.ContextInterface();

	ConcreteStragtegyB stragtegyB;
	Context context1(stragtegyB);
	context1.ContextInterface();

	ConcreteStragtegyC stragtegyC;
	Context context2(stragtegyC);
	context2.ContextInterface();
	return 1;
}

利用單純策略模式解決商城自費調整的問題:

策略類:

//cash.h
class CashSuper
{
public:
	virtual double acceptCash(double money) = 0;
};
class CashNormal : public CashSuper
{
public:
	double acceptCash(double money)
	{
		return money;
	}
};
class CashRebate : public CashSuper
{
public:
	CashRebate(double rebate){moneyRebate = rebate;}
public:
	double acceptCash(double money)
	{
		return money*moneyRebate;
	}
private:
	double moneyRebate;
};
class CashReturn : public CashSuper
{
public:
	CashReturn(double condition,double returnback)
	{
		moneyCondition = condition;
		moneyReturn = returnback;
	}
public:
	double acceptCash(double money)
	{
		if(money > moneyCondition)
		{
			return money - ((int)money / (int)moneyCondition)*moneyReturn;
		}
		else
			return money;
	}
private:
	double moneyCondition;
	double moneyReturn;
};
上下文類
class CashContext
{
public:
	CashContext(CashSuper *type)
	{
		this->cashType = type;
	}
	~CashContext()
	{
		if(cashType != NULL)
			delete cashType;
		cashType = NULL;
	}
	double getResult(double money)
	{
		return cashType->acceptCash(money);
	}
private:
	CashSuper *cashType;
};

客戶端方法:
#include <stdio.h>
#include "context.h"
//單純的策略模式
//裡面還是需要知道cashType類和CashContext類,兩個類。並沒有做到降低耦合度的要求,
//而且還需要再客戶端判斷到底是建立哪一個cashType類。
//所以最好將策略模式與工廠模式結合使用,可以降低耦合度,並且客戶端不用判斷要建立哪個物件。
int main()
{
	CashContext *test1 = new CashContext(new CashNormal());
	printf("%f \n",test1->getResult(500));
	delete test1;
	test1 = new CashContext(new CashRebate(0.6));
	printf("%f \n",test1->getResult(500));
	delete test1;
	test1 = new CashContext(new CashReturn(300,100));
	printf("%f \n",test1->getResult(500));
	delete test1;
	return 1;
}

策略模式與簡單工廠模式結合

策略類與上面的相同。

上下文類:

//與工廠模式結合的策略模式
class CashContextWithFactory
{
public:
	
	CashContextWithFactory(char *in)
	{

		if(strcmp(in,"正常收費")==0)
		{
			cashType = new CashNormal();
		}
		else if(strcmp(in,"滿300減100")==0)
		{
			cashType = new CashReturn(300,100);
		}
		else if(strcmp(in,"打6折")==0)
		{
			cashType = new CashRebate(0.6);
		}
	}
	~CashContextWithFactory()
	{
		if(cashType != NULL)
			delete cashType;
		cashType = NULL;
	}
	double getResult(double money)
	{
		return cashType->acceptCash(money);
	}
private:
     CashSuper *cashType;

};

客戶端方法:
//與工廠模式結合的設計模式
//客戶端部需要判斷建立哪個物件,只需要輸入對應的條件就可以
//客戶端中只需要知道CashContextWithFactory類就可以,使得客戶端與具體收費演算法徹底分離,不需要再客戶端中判斷呼叫哪個演算法的物件
//策略模式的另一個特點是每一個演算法都有自己單獨的類,可以利用演算法介面進行單獨測試
//修改某個演算法只需要修改其類就可以,不需要動其他的類
//不過,在CashContextWithFactory裡面還是利用了switch來判斷建立哪種演算法,後面將學習反射模式,可以解決該問題。
int main()
{
	CashContextWithFactory *test1 = new CashContextWithFactory("正常收費");
	printf("%f \n",test1->getResult(500));
	delete test1;
	test1 = new CashContextWithFactory("滿300減100");
	printf("%f \n",test1->getResult(500));
	delete test1;
	test1 = new CashContextWithFactory("打6折");
	printf("%f \n",test1->getResult(500));
	delete test1;
	return 1;
}