設計模式那點事--策略模式

       概念:

       策略模式定義了一系列的算法,分別封裝起來,它們之間可以相互替換。此模式讓算法的變化,不會影響到使用算法的客戶策略,實質上指的是算法。

       例子:

       一個鮮活簡單的例子總能讓人輕鬆地理解晦澀的概念。我們來看看一個關於汽車價格的策略模式。

       我們知道,汽車的品牌和質量,決定了它的價格。就像寶馬(BMW),法拉利(Ferrali)和奔馳(Benz)三輛汽車,它們的價格肯定是不一樣的。那如果想要知道它的價格的話,可以詢問銷售人員等等。但是在計算機裏,我們可不能直接問銷售人員啊!

       對於它們來說,雖然各自價格不同,是不同的算法,但是獲取價格卻是一種公共操作(策略模式要求的就是要封裝變化的算法)。於是,可以創建一個抽象父類汽車類(Car),聲明一個獲取價格virtual GetPrice函數的接口。然後創建三個子類:BMW,Ferrali和Benz,分別繼承於Car。通過繼承關係,每個子類可以改寫父類的GetPrice函數,然後在客戶端中通過調用不同的汽車子類算法來獲取子類汽車價格。

       總結一下:

       1、我們把父類Car當成是抽象策略類,提供了一個獲取價格的GetPrice接口;

       2、每種包含獲取價格GetPrice的汽車類爲具體策略類(每種牌子的車價格不一致,導致不同計算算法),要重寫父類CarGetPrice函數;

       3、建立一個環境上下文類PriceContext,維護一個對父類Car對象(指針對象才能實現多態)的引用,最後給客戶端調用具體的策略類對象。

     UML圖:



    代碼:

#include <iostream>
using namespace std;

class Car
{
public:
	float m_fPrice;
	
public:
	virtual float GetPrice()
	{
		return m_fPrice*1;
	}
};

class BMW:public Car
{
public:
	float GetPrice()
	{
		return m_fPrice*3;
	}
};

class Ferrali:public Car
{
public:
	float GetPrice()
	{
		return m_fPrice*11;
	}
};

class Benz:public Car
{
public:
	float GetPrice()
	{
		return m_fPrice*6;
	}
};

class PriceContext
{
public:
	int m_iFlag;

private:
	Car* m_cCar;

public:
	PriceContext(Car* cCar):m_cCar(cCar)
	{
		//this->m_cCar = cCar;
	}

	float GetPriceContext()
	{
		m_cCar->m_fPrice = 10000;
		return(m_cCar->GetPrice());
	}
};

int main()
{
	float fPrice=0.0;
	int iTag=0;

 	cout<<"----策略模式開始----"<<endl;
 	cout<<"BMW:1,Ferrali:2,Benz:3"<<endl;
 	cout<<"請輸入您想要查詢的汽車價格:";
 	cin>>iTag;

	PriceContext* priceContext;

	switch (iTag)
	{
	case 1:
		priceContext = new PriceContext(new BMW);
		break;
	case 2:
		priceContext = new PriceContext(new Ferrali);
		break;
	case 3:
		priceContext = new PriceContext(new Benz);
		break;
	default:
		priceContext = new PriceContext(new Car);
		break;
	}

	fPrice = priceContext->GetPriceContext();

	delete priceContext;
	priceContext = NULL;
 	
 	cout<<"價格爲:"<<fPrice<<endl;
 	cout<<"----策略模式結束----"<<endl;
	
	return 1;
}

   策略模式和簡單工廠模式相結合

    簡單工廠模式中,對象的動態創建判斷放在了工廠類中。而基本的策略模式客戶端還是要進行算法判斷和對象創建。因此可模仿簡單工廠,把算法的判斷移到環境上下文類中,儘量減少客戶端職責,降低耦合性。其中相對簡單工廠模式來說,客戶端中連基類都不出現,更加地隱藏算法的具體實現細節。

    代碼:

class PriceContext
{
public:
	int m_iFlag;

private:
	Car* m_cCar;

public:
	PriceContext(int iFlag)  //構造中不再穿對象,傳標識
	{
		switch (iFlag)
		{
		case 1:
			m_cCar = new BMW;
			break;
		case 2:
			m_cCar = new Ferrali;
			break;
		case 3:
			m_cCar = new Benz;
			break;
		default:
			m_cCar = new Car;
			break;
		}
	}

	float GetPriceContext()
	{
		m_cCar->m_fPrice = 10000;
		return(m_cCar->GetPrice());
	}
};

int main()
{
	float fPrice=0.0;
	int iTag=0;

 	cout<<"----策略模式開始----"<<endl;
 	cout<<"BMW:1,Ferrali:2,Benz:3"<<endl;
 	cout<<"請輸入您想要查詢的汽車價格:";
 	cin>>iTag;

	PriceContext* priceContext = new PriceContext(iTag);

	fPrice = priceContext->GetPriceContext();

	delete priceContext;
	priceContext = NULL;
 	
 	cout<<"價格爲:"<<fPrice<<endl;
 	cout<<"----策略模式結束----"<<endl;
	
	return 1;
}

    總結:

    1、策略模式定義了一系列的算法,從概念上看,所有算法完成的都是相同的操作,只是表現行爲不同。通過相同的方式調用所有的算法(使用多態),減少了算法類與使用算法類之間的耦合;

    2對客戶隱藏具體策略(算法)的實現細節,彼此完全獨立

    3、策略模式簡化了單元測試,每個算法都有自己的類,可以通過自己的接口單獨測試;

    4客戶端必須知道所有的策略類,並自行決定使用哪一個策略類。這就意味着客戶端必須理解這些算法的區別,以便適時選擇恰當的算法類。換言之,策略模式只適用於客戶端知道所有的算法或行爲的情況


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章