設計模式(五)抽象工廠 C++

每一個設計模式的產生都是 爲了應對某些應用場景。

        簡單工廠可以由一個工廠生產不同的產品,缺點是如果不斷增加產品,則需要不斷修改工廠,違反了開放封閉原則,(類、模塊、函數可以擴展,但是不可以修改)。

        於是,就出現了工廠方法模式。所謂工廠方法模式,是指定義一個用於創建對象的接口,讓子類決定實例化哪一個類。打個比方

現在有A、B兩種產品,那麼久開兩個工廠。工廠A負責生產A產品,工廠B負責生產B種產品。這時候客戶不需要告訴工廠生產哪種產品了。需要A產品,直接通知A工廠就好了,需要B產品,直接通知B工廠就好了。工廠方法和簡單工廠的區別,在於開放封閉原則。

        但是隨着業務的變化,設計模式可能也需要隨着變化。比如說,我們爲客戶安裝了一個MySQL數據庫,裏面有兩張表,UserTable(用戶表)和ApartmentTable(部門表),但是未來某一天用戶可能會用Access來存放這兩張表,怎麼辦?工廠方法?但是工廠方法是一對一的,一個工廠生產一個產品,在這裏如果說把MySQL下的User表作爲一個產品,然後爲MySQL下的User表創建一個工廠?這樣一來在整個過程中會有四個工廠。爲每張表創建一個工廠也能夠解決問題,但是這不是最好的方法。因爲無論兩個數據庫下的兩張User表,還是Apartment表還是有相似性的,換句話說需要創建的對象是一系列相互關聯或相互依賴的產品族,能不能根據這些相似性進行抽象呢?

這個時候要考慮抽象工廠模式。還是開設兩家工廠,工廠A負責生產A1 、A2型號產品,B工廠負責生產B1、B2型號的產品。  

在這個業務場景下就是兩個數據工廠,MySQL生產AccessUser,AccessApartment,Access生產 AccessUser ,AccessApartment。

代碼實現如下

#include <iostream>    
#include <windows.h>
using namespace std;

//定義抽象類(用戶表) 
class productUserTable
{
public:
	virtual void show() = 0;
};

//定義抽象類 (部門表) 
class productAprtmentTable
{
public:
	virtual void show() = 0;
};

// 數據庫抽象類作爲抽象工廠
class FactoryDB
{
public:
	virtual productUserTable *CreateUserTable() = 0;
	virtual productAprtmentTable *CreateApartmentTable() = 0;
};

//定義具體類  ,具體的用戶表
class MySQLUserTable :public productUserTable
{
public:
	void show() 
	{ 
		cout << "product MySQLUserTable" << endl; 
	}
};

class AccessUserTable :public productUserTable
{
public:
	void show() 
	{ 
		cout << "product AccessUserTable" << endl;
	}
};

//定義具體類 ,具體的產品表 
class MySQLAprtmentTable :public productAprtmentTable
{
public:
	void show() 
	{ 
		cout << "product MySQLAprtmentTable" << endl; 
	}
};

class AccessAprtmentTable :public productAprtmentTable
{
public:
	void show()
	{ 
		cout << "product AccessAprtmentTable" << endl; 
	}
};

// MySQL數據庫下的 User 表、Apartment表、所以MySQL爲當前工廠
class FactoryMySQL:public FactoryDB
{
public:
	productUserTable *CreateUserTable() 
	{ 
		return new MySQLUserTable();
	}
	productAprtmentTable *CreateApartmentTable()
	{ 
		return new MySQLAprtmentTable(); 
	}
};

// Access數據庫下的 User 表、Apartment表,所以Access爲當前工廠
class FactoryAccess :public FactoryDB
{
public:
	productUserTable *CreateUserTable() 
	{ 
		return new AccessUserTable();
	}
	productAprtmentTable *CreateApartmentTable()
	{ 
		return new AccessAprtmentTable();
	}
};

int main()
{
	FactoryMySQL *factoryA = new FactoryMySQL();
	factoryA->CreateUserTable()->show();
	factoryA->CreateApartmentTable()->show();

	FactoryAccess *factoryB = new FactoryAccess();
	factoryB->CreateUserTable()->show();
	factoryB->CreateApartmentTable()->show();

	system("pause");
	return 0;
}

抽象工廠模式的優點

抽象工廠模式除了具有工廠方法模式的優點外,最主要的優點就是可以在類的內部對產品族進行約束。所謂的產品族,一般或多或少的都存在一定的關聯,抽象工廠模式就可以在類內部對產品族的關聯關係進行定義和描述,而不必專門引入一個新的類來進行管理。

抽象工廠模式的缺點

產品族的擴展將是一件十分費力的事情,假如產品族中需要增加一個新的產品,則幾乎所有的工廠類都需要進行修改。所以使用抽象工廠模式時,對產品等級結構的劃分是非常重要的。

適用場景

當需要創建的對象是一系列相互關聯或相互依賴的產品族時,便可以使用抽象工廠模式。說的更明白一點,就是一個繼承體系中,如果存在着多個等級結構(即存在着多個抽象類),並且分屬各個等級結構中的實現類之間存在着一定的關聯或者約束,就可以使用抽象工廠模式。假如各個等級結構中的實現類之間不存在關聯或約束,則使用多個獨立的工廠來對產品進行創建,則更合適一點。

總結

無論是簡單工廠模式,工廠方法模式,還是抽象工廠模式,他們都屬於工廠模式,在形式和特點上也是極爲相似的,他們的最終目的都是爲了解耦。在使用時,我們不必去在意這個模式到底工廠方法模式還是抽象工廠模式,因爲他們之間的演變常常是令人琢磨不透的。經常你會發現,明明使用的工廠方法模式,當新需求來臨,稍加修改,加入了一個新方法後,由於類中的產品構成了不同等級結構中的產品族,它就變成抽象工廠模式了;而對於抽象工廠模式,當減少一個方法使的提供的產品不再構成產品族之後,它就演變成了工廠方法模式。

所以,在使用工廠模式時,只需要關心降低耦合度的目的是否達到了。

發佈了195 篇原創文章 · 獲贊 41 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章