每一個設計模式的産生都是 為了應對某些應用場景。
簡單工廠可以由一個工廠生産不同的産品,缺點是如果不斷增加産品,則需要不斷修改工廠,違反了開放封閉原則,(類、子產品、函數可以擴充,但是不可以修改)。
于是,就出現了工廠方法模式。所謂工廠方法模式,是指定義一個用于建立對象的接口,讓子類決定執行個體化哪一個類。打個比方
現在有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;
}
抽象工廠模式的優點
抽象工廠模式除了具有工廠方法模式的優點外,最主要的優點就是可以在類的内部對産品族進行限制。所謂的産品族,一般或多或少的都存在一定的關聯,抽象工廠模式就可以在類内部對産品族的關聯關系進行定義和描述,而不必專門引入一個新的類來進行管理。
抽象工廠模式的缺點
産品族的擴充将是一件十分費力的事情,假如産品族中需要增加一個新的産品,則幾乎所有的工廠類都需要進行修改。是以使用抽象工廠模式時,對産品等級結構的劃分是非常重要的。
适用場景
當需要建立的對象是一系列互相關聯或互相依賴的産品族時,便可以使用抽象工廠模式。說的更明白一點,就是一個繼承體系中,如果存在着多個等級結構(即存在着多個抽象類),并且分屬各個等級結構中的實作類之間存在着一定的關聯或者限制,就可以使用抽象工廠模式。假如各個等級結構中的實作類之間不存在關聯或限制,則使用多個獨立的工廠來對産品進行建立,則更合适一點。