1. 程式人生 > >設計模式那點事--策略模式

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

簡化 cas enter ext font 想要 fonts 對象創建 客戶

概念:

策略模式定義了一系列的算法,分別封裝起來,它們之間能夠相互替換。

此模式讓算法的變化,不會影響到使用算法的客戶策略,實質上指的是算法。

樣例:

一個鮮活簡單的樣例總能讓人輕松地理解晦澀的概念。

我們來看看一個關於汽車價格的策略模式。

我們知道。汽車的品牌和質量。決定了它的價格。

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

對於它們來說。盡管各自價格不同。是不同的算法。可是獲取價格卻是一種公共操作(策略模式要求的就是要封裝變化的算法)。於是。能夠創建一個抽象父類汽車類(Car

),聲明一個獲取價格virtual GetPrice函數的接口

然後創建三個子類:BMW,Ferrali和Benz,分別繼承於Car。通過繼承關系,每一個子類能夠改寫父類的GetPrice函數,然後在client中通過調用不同的汽車子類算法來獲取子類汽車價格。

總結一下:

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

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

3、建立一個環境上下文類PriceContext,維護一個對父類

Car對象(指針對象才幹實現多態)的引用。最後給client調用詳細的策略類對象。

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;
}

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

簡單工廠模式中。對象的動態創建推斷放在了工廠類中。

而主要的策略模式client還是要進行算法推斷和對象創建。

因此可模仿簡單工廠,把算法的推斷移到環境上下文類中,盡量降低client職責,降低耦合性。當中相對簡單工廠模式來說,client中連基類都不出現,更加地隱藏算法的詳細實現細節。

代碼:

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、策略模式簡化了單元測試,每一個算法都有自己的類。能夠通過自己的接口單獨測試;

4client必須知道全部的策略類,並自行決定使用哪一個策略類。這就意味著client必須理解這些算法的差別,以便適時選擇恰當的算法類。換言之,策略模式僅僅適用於client知道全部的算法或行為的情況


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