我所理解的設計模式(C++實現)——抽象工廠模式(Abstract Factory Pattern)

解決的問題:

       在系統裏a,b,c三個組件必須同時使用,但是a的同類 a1和a2這三種方法有共同特點但是是互斥的,b,b1,b2和c,c1,c2和a/a1/a2是一樣的。就比如說創建在不同操作系統的視窗環境下都能夠運行的系統時,Unix下面有unixButton和 unixText,Win下面也有winButton和winText,unixButton和unixText必須在一個系統unix裏面用,而winButton和winText只能在Win下面用。但是winButton和unixButton這兩種東西都是有相同的特點的,比如說按下去之後會觸發事件,比如說他上面有文字描述等等,但是winButton和unixButton卻又是不可以混用的。

     那麼此問題就可以用抽象工廠很好的解決:
     在抽象工廠模式中如何選擇使用 winButton ,winText,有具體的工廠類winFactory來負責,因爲他們含有選擇合適的產品對象的邏輯,所以是與應用系統的商業邏輯緊密相關的。而抽象工廠類來負責定義接口,他纔是抽象工廠模式的核心。
     而winButton/macButton則是一種產品族,有共同的特點,他們具體特點有抽象產品類或者接口來定義和描述。但是他們具體的實現有具體的產品類負責,這些是客戶端最終想要的東西,所以其內部一定充滿了應用系統的商業邏輯(觸發邏輯/樣式邏輯等)。

類圖結構:    



樣例實現:

// CplusplusAbstractFactory.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<typeinfo>
// "AbstractProductA" 草食動物
class Herbivore
{
};

// "AbstractProductB" 食肉動物
class Carnivore
{
public:
	// Methods
	virtual void Eat( Herbivore *h ) {};
};

// "ProductA1"
class Wildebeest : public Herbivore
{
};

// "ProductA2"
class Bison : public Herbivore
{
};

// "ProductB1"
class Lion : public Carnivore
{

public:
	// Methods
	void Eat( Herbivore *h )
	{
		// eat wildebeest	 
		printf("Lion eats %s\n",typeid(h).name());
	}
};

// "ProductB2"
class Wolf : public Carnivore
{

public:
	// Methods
	void Eat( Herbivore *h )
	{
		// Eat bison
		printf("Wolf eats %s\n",typeid(h).name());
	}
};

// "AbstractFactory"
class ContinentFactory
{
public:
	// Methods
	virtual Herbivore* CreateHerbivore()
	{
		return new Herbivore();
	}
	virtual Carnivore* CreateCarnivore()
	{
		return new Carnivore();
	}
};

// "ConcreteFactory1"
class AfricaFactory : public ContinentFactory
{
public:
	// Methods
	Herbivore* CreateHerbivore()
	{ 
		return new Wildebeest(); 
	}

	Carnivore* CreateCarnivore()
	{ 
		return new Lion(); 
	}
};

// "ConcreteFactory2"
class AmericaFactory : public ContinentFactory
{
public:
	// Methods
	Herbivore* CreateHerbivore()
	{ 
		return new Bison(); 
	}

	Carnivore* CreateCarnivore()
	{ 
		return new Wolf(); 
	}
};



// "Client"
class AnimalWorld
{
private:
	// Fields
	Herbivore* herbivore;
	Carnivore* carnivore;

public:
	// Constructors
	AnimalWorld( ContinentFactory *factory )
	{
		carnivore = factory->CreateCarnivore();
		herbivore = factory->CreateHerbivore();
	}

	// Methods
	void RunFoodChain()
	{ 
		carnivore->Eat(herbivore); 
	}
};


int _tmain(int argc, _TCHAR* argv[])
{
	// Create and run the Africa animal world
	ContinentFactory *africa = new AfricaFactory();
	AnimalWorld *world = new AnimalWorld( africa );
	world->RunFoodChain();

	// Create and run the America animal world
	ContinentFactory *america = new AmericaFactory();
	world = new AnimalWorld( america );
	world->RunFoodChain();

	return 0;
}

“開放-封閉”原則:


抽象工廠可以很好的應對增加新產品族的問題(即a4/b4/c4),且符合“開放-封閉”原則,但是若是增加新的產品結構的話(即d/d1/d2),就是說a/b/c/d這4中方法必須同時使用了,那就必須修改工廠角色。不符合“開放-封閉”原則。綜合來講,抽象工廠模式以一種傾斜的方式支持增加新的產品,它爲新產品族的增加提供方便,而不能爲新的產品結構的增加提供這樣的方便。

實現要點:

  • 在抽象工廠模式中,選用哪種產品族的問題,需要採用工廠方法或簡單工廠模式來配合解決。
  • 抽象工廠模式和工廠方法模式一樣,都把對象的創建延遲到了他的子類中。
  • 具體的工廠類可以設計成單例類,他只向外界提供自己唯一的實例。

與其他工廠模式的聯繫和異同:

  • 抽象工廠模式中的具體工廠負責生產一個產品族的產品。而產品族的增加只需要增加與其對應的具體工廠。
  • 3種工廠模式都是創建型模式,都是創建對象的,但都把產品具體創建的過程給隱藏了。
  • 工廠方法模式是針對一種產品結構,而抽象工廠模式是針對多種產品結構。

適用性:

在以下情況下應當考慮使用抽象工廠模式:

  • 一個系統不應當依賴於產品類實例如何被創建、組合和表達的細節,這對於所有形態的工廠模式都是重要的。
  • 這個系統有多於一個的產品族,而系統只消費其中某一產品族。
  • 同屬於同一個產品族的產品是在一起使用的,這一約束必須在系統的設計中體現出來。
  • 系統提供一個產品類的庫,所有的產品以同樣的接口出現,從而使客戶端不依賴於實現。

應用場景:

  • 支持多種觀感標準的用戶界面工具箱(Kit)。
  • 遊戲開發中的多風格系列場景,比如道路,房屋,管道等。

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