策略模式(strategy)- 設計模式(十三)

作用

定義一系列的算法,把它們一個個封裝起來,並且使它們可相互替換。本模式使得算法可獨立於使用它的客戶而變化。也就是說,從表面上看,這一系列的算法實現相同的功能,提供一樣的接口,是可以相互替換的,但是每個算法的內部實現可能不一樣。
簡而言之一句話,Strategy 模式是對算法的封裝。處理一個問題的時候可能有多種算法,這些算法的接口 (輸入參數,輸出參數等)都是一致的,那麼可以考慮採用Strategy 模式對這些算法進行封裝,在基類中定義一個函數接口就可以了。

舉個例子

想喫雞腿,樓下有兩家便利店,都可以賣雞腿,那麼,我們就可以選擇取任何一家便利店,叫兒子去買,最終的結果都是兒子買回來了雞腿,順便給自己買了個冰激凌。
我們可以把去一家便利店買雞腿看作是一個算法,那個就有兩個算法,輸入和輸出(買回雞腿)都是一樣的。
那麼兒子就是其中的環境類,而你是客戶端,告訴兒子想喫哪家便利店的雞腿。

優點

  • 策略模式是定義一系列算法的方法,概念上,這些算法是可以相互代替的。
  • 策略模式的Strategy類層次爲Context定義了一系列的可供重用的算法或行爲。繼承有助於析取出這些算法中的公共功能。
  • 每個算法都有自己的類,測試每個算法只是調用對應的接口就行,因此簡化了測試。

缺點

  • 選擇調用的算法有客戶端承擔,並沒有降低客戶端選擇判斷的壓力。
  • 客戶端承擔了選擇的權利,因此客戶端就有了知道算法具體實現的可能性,上面的例子,選擇哪家便利店,只有明確知道每家店的雞腿的口味,才能夠準確的選擇便利店。
  • 無論後面的每個算法實現簡單與複雜,這些算法都繼承共享Strategy類定義的接口,因此,可能會產生一些根本用不到的參數,比如假設便利店有很多,但是每次買雞腿只會挑一個去買,但是對於兒子來說,剩下 的哪些便利店的信息都需要知道。(畢竟喜歡喫的冰激凌可能在其他的便利店裏面有賣)
    特點:
  • 策略模式的重心不是算法的具體實現,而是怎樣對這寫算法進行組合、調用,這樣會使得程序更靈活,可維護性和可擴展性比較好。
  • 所有的算法都可以替換,因此這些算法是具有平等性的,所有的算法實現的實現之間是完全獨立的。
  • 雖然算法有很多,但是使用的時候只能選擇一個算法,因此在運行的時候,這些算法是互斥的,可以在運行的過程中動態的切換某一種策略,但是隻能選擇其中的一種。
  • 所有算法如果有公共的行爲,那麼這些公共的行爲是放在Strategy類裏面的。
  • 算法的實現過程中有很多,只有當客戶端運行時候才知道具體調用哪一種算法,就比如,便利店是客觀存在的,只有在想喫雞腿的時候纔會決定去買哪一家的。

與其他設計模式的區別

  • 狀態模式: 每個對象可以在其內部動態的改變自己的狀態,對象狀態的改變可以不停的執行的模式
  • 工廠模式: 注重對象的創建,對象的創建和調用與客戶端無關,新增一個產品必須新增一個工廠,對象只知道工廠,具體的創建對象並不知道,子類決定了類的實例化
  • 模版方法: 和策略模式最像,模版模式主要是類的繼承,而策略模式着重於類的組合,兩者的區別也就是類的繼承和組合之間的區別
  • 策略模式: 初始時改變,已經確定需要執行的算法,只執行一次,獨立於客戶端運行

UML 結構圖

在這裏插入圖片描述

例子

#include <iostream>

using namespace std;

class Strategy
{
public:
	
	virtual ~Strategy(){}
	
	virtual void BuyChicken() = 0;
};

class StoreA : public Strategy
{
public:
	virtual ~StoreA(){}
	
	virtual void BuyChicken()
	{ 
		cout << "The chicken leg was bought by StoreA... " << endl; 
	}
};

class StoreB : public Strategy
{
public:
	virtual ~StoreB(){}
	
	virtual void BuyChicken()
	{ 
		cout << "The chicken leg was bought by StoreB... " << endl; 
	}
};

class Context
{
public:
	Context(Strategy* pStrategy):m_pStrategy(pStrategy){}
	~Context()
	{
		delete m_pStrategy;
		m_pStrategy = NULL;
	}
	void ContextInterface()
	{
		if(NULL != m_pStrategy)
		{
			m_pStrategy->BuyChicken();	
		}
	}
private:
	Strategy* m_pStrategy;
};

int main(int argc, char* argv[])
{
	Strategy* p1 = new StoreB();
	Context* p2 = new Context(p1);	//客戶端在這個時候已經選定了算法
	p2->ContextInterface();
	
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章