定義:為建立一組相關或互相依賴的對象提供一個接口,而且無需指定他們的具體類。
類型:建立類模式
用途:工廠模式主要是為建立對象提供過渡接口,以便将建立對象的具體過程屏蔽隔離起來,降低耦合度
達到提高靈活性的目的。
類圖:
現在一般看來将工廠模式分為三類:
1)簡單工廠模式(simple factory)
2)工廠方法模式(factory method)
3)抽象工廠模式(abstract factory)
這三種模式從上到下逐漸抽象,并且更具一般性。
gof在《設計模式》一書中将工廠模式分為兩類:
工廠方法模式(factory method)與抽象工廠模式(abstract factory)。
将簡單工廠模式(simple factory)看為工廠方法模式的一種特例,兩者歸為一類。
但是兩種看法本質上是一緻的,而且我們沒必要深究那麼多,下面來看看這些工廠模式是怎麼來“治病”的。
工廠模式屬于建立型模式,大緻可以分為三類,簡單工廠模式、工廠方法模式、抽象工廠模式。聽上去差不多,都是工廠模式。
下面一個個介紹,首先介紹簡單工廠模式,它的主要特點是需要在工廠類中做判斷,進而創造相應的産品。當增加新的産品時,就需要修改工廠類。有點抽象,
舉個例子就明白了。有一家生産處理器核的廠家,它隻有一個工廠,能夠生産兩種型号a,b的處理器核。不同的客戶有不同的需求,有的客戶喜歡a核,有的客戶偏愛b核,怎麼滿足這種需求呢,
簡單工廠,客戶需要什麼樣的處理器核,一定要顯示地告訴生産工廠。下面給出一種實作方案。
簡單工廠模式又稱靜态工廠方法模式。從命名上就可以看出這個模式一定很簡單。它存在的目的很簡單:定義一個用于建立對象的接口
先來看看它的組成
① 工廠類角色:這是本模式的核心,含有一定的商業邏輯和判斷邏輯。它往往由一個具體類實作。
② 抽象産品角色:它一般是具體産品繼承的父類或者實作的接口。由接口或者抽象類來實作。
③ 具體産品角色:工廠類所建立的對象就是此角色的執行個體。由一個具體類實作。
#include <iostream>
// 生成産品依據辨別
typedef enum classtype
{
singcore_a,
singcore_b,
}classtype;
////////////////////////////////////////////////////////////////////////////////
// 基礎産品類 -=> 對應于抽象産品角色
class singcore
public :
virtual ~singcore( ){ }; // 虛析構函數
virtual void show( ) = 0; // 産品的顯示函數
};
// 單核産品s -=> 對應于具體産品角色
class singcorea : public singcore
virtual ~singcorea( ){ }; // 虛析構函數
void show( )
{
std::cout <<"singcore a..." <<std::endl;
}
};
// 單核産品b -=> 對應于具體産品角色
class singcoreb : public singcore
virtual ~singcoreb( ){ }; // 虛析構函數
std::cout <<"singcore b..." <<std::endl;
}
};
//
// 工廠類 -=> 對應于工廠角色
class factory
virtual ~factory( ){ }; // 虛析構函數
singcore* createsingcore(classtype classtype)
{
switch(classtype)
{
case singcore_a :
{
return new singcorea( );
}
case singcore_b :
return new singcoreb( );
}
int main()
factory *factory = new factory( );
factory->createsingcore(singcore_a)->show( );
factory->createsingcore(singcore_b)->show( );
delete factory;
}
首先,使用了簡單工廠模式後,我們的程式更加符合現實中的情況;而且用戶端免除了直接建立産品對象的責任,而僅僅負責“消費”産品,使用戶端不再依賴與具體産品的建立,就像我們買産品a和産品b,我們隻關心它是不是我們需要的産品,并不關心它是怎麼被建立的。
但是這樣設計的也有缺點,就是要增加新的核類型時,就需要修改工廠類。這就違反了開放封閉原則:軟體實體(類、子產品、函數)可以擴充,但是不可修改。可想而知對于新産品的加入,工廠類是很被動的。對于這樣的工廠類,我們稱它為全能類或者上帝類。
我們舉的例子是最簡單的情況,而在實際應用中,很可能産品是一個多層次的樹狀結構。由于簡單工廠模式中隻有一個工廠類來對應這些産品,是以這可能會把我們的上帝累壞了,也累壞了我們這些程式員
于是工廠方法模式作為救世主出現了。
所謂工廠方法模式,是指定義一個用于建立對象的接口,讓子類決定執行個體化哪一個類。
factory method工廠方法模式使一個類的執行個體化延遲到其子類。
工廠方法模式去掉了簡單工廠模式中工廠方法的靜态屬性,使得它可以被子類繼承。
這樣在簡單工廠模式裡集中在工廠方法上的壓力可以由工廠方法模式裡不同的工廠子類來分擔。
你應該大緻猜出了工廠方法模式的結構,來看下它的組成:
① 抽象工廠角色: 這是工廠方法模式的核心,它與應用程式無關。是具體工廠角色必須實作的接口或者必須繼承的父類。它由抽象類或者接口來實作。
② 具體工廠角色:它含有和具體業務邏輯有關的代碼。由應用程式調用以建立對應的具體産品的對象。
③ 抽象産品角色:它是具體産品繼承的父類或者是實作的接口。一般有抽象類或者接口來實作。
④具體産品角色:具體工廠角色所建立的對象就是此角色的執行個體。由具體的類來實作。
還是以剛才的例子解釋。這家生産處理器核的産家賺了不少錢,于是決定再開設一個工廠專門用來生産b型号的單核,而原來的工廠專門用來生産a型号的單核。這時,客戶要做的是找好工廠,比如要a型号的核,就找a工廠要;否則找b工廠要,不再需要告訴工廠具體要什麼型号的處理器核了。
////////////////////////////////////////////////////////////////////////////////
// 核心産品基類 -=> 對應于抽象産品角色
virtual ~singcore( ){ }; // 虛析構函數
virtual void show( ) = 0; // 産品顯示函數
// 核心産品a -=> 對應于具體産品角色
class singcorea : public singcore
virtual ~singcorea( ){ }; // 虛析構函數
void show( ) // 産品顯示函數
}
// 核心産品b -=> 對應于具體産品角色
void show( ) // 産品顯示函數
std::cout <<"singcore b..." <<std::endl;
//
// 工廠的基類 -=> 對應于抽象工廠角色
public:
virtual ~factory( ){ }; // 虛析構函數
virtual singcore* createsingcore( ) = 0; // 生産産品的生産線
// 生産核心a的工廠 -=> 對應于具體産品角色
class factorya : public factory
virtual ~factorya( ){ }; // 虛析構函數
singcorea* createsingcore( )
return new singcorea( );
// 生産核心b的工廠 -=> 對應于具體産品角色
class factoryb : public factory
public :
virtual ~factoryb( ){ }; // 虛析構函數
singcoreb* createsingcore( )
return new singcoreb( );
int main( )
factory *factorya = new factorya( );
factorya->createsingcore( )->show( );
factory *factoryb = new factoryb( );
factoryb->createsingcore( )->show( );
return 0;
工廠方法模式使用繼承自抽象工廠角色的多個子類來代替簡單工廠模式中的“上帝類”。正如上面所說,這樣便分擔了對象承受的壓力;而且這樣使得結構變得靈活起來——當有新的産品産生時,隻要按照抽象産品角色、抽象工廠角色提供的合同來生成,那麼就可以被客戶使用,而不必去修改任何已有的代碼。可以看出工廠角色的結構也是符合開閉原則的!就相當于市面上同樣的産品有很多個牌子,有a牌子和b牌子,每家都有一個單獨的工廠用來生産。這樣每次增加一個新的牌子的産品上市,都會有一家新的工廠出現。
好了那到底什麼是抽象工工廠呢,它到底有什麼作用呢?
在将抽象工廠前我們先來認識一下産品族。
還是舉這個例子,這家公司的技術不斷進步,不僅可以生産單核處理器,也能生産多核處理器。每個處理器下都有a,b兩種型号的。那麼這裡a單核和b單核就同屬于一個單核産品族。a多核和b多核就同屬于一個多核産品族。
對于這種情況,就需要用到抽象工廠了。它的定義為提供一個建立一系列相關或互相依賴對象的接口,而無需指定它們具體的類。具體這樣應用,這家公司還是開設兩個工廠,一個專門用來生産a型号的單核多核處理器,而另一個工廠專門用來生産b型号的單核多核處理器,每個工廠用來生産一個産品族。
抽象工廠模式的用意為:給用戶端提供一個接口,可以建立多個産品族中的産品對象
而且使用抽象工廠模式還要滿足一下條件:
①系統中有多個産品族,而系統一次隻可能消費其中一族産品。
②同屬于同一個産品族的産品以其使用。
看看抽象工廠模式的各個角色(和工廠方法的如出一轍):
①抽象工廠角色: 這是工廠方法模式的核心,它與應用程式無關。是具體工廠角色必須實作的接口或者必須繼承的父類。它由抽象類或者接口來實作。
②具體工廠角色:它含有和具體業務邏輯有關的代碼。由應用程式調用以建立對應的具體産品的對象。它由具體的類來實作。
④具體産品角色:具體工廠角色所建立的對象就是此角色的執行個體。由具體的類來實作
可以說,抽象工廠模式和工廠方法模式的差別就在于需要建立對象的複雜程度上。
而且抽象工廠模式是三個裡面最為抽象、最具一般性的。
你能見到的大部分抽象工廠模式都是這樣的:它的裡面是一堆工廠方法,每個工廠方法傳回某種類型的對象。
如果說抽象工廠中的工廠是一個實際的工廠的話,那麼工廠方法中的工廠更像現實中工廠的一條生産線
下面舉個例子具體描述一下
①比如說工廠可以生産滑鼠和鍵盤。那麼抽象工廠的實作類(它的某個具體子類)的對象都可以生産滑鼠和鍵盤,但可能工廠a生産的是羅技的鍵盤和滑鼠,工廠b是微軟的。這樣a和b就是工廠,對應于抽象工廠;每個工廠生産的滑鼠和鍵盤就是産品,對應于工廠方法;用了工廠方法模式,你替換生成鍵盤的工廠方法,就可以把鍵盤從羅技換到微軟, 但是滑鼠還是原來羅技的但是用了抽象工廠模式,你隻要換家工廠,就可以同時替換滑鼠和鍵盤一套。如果你要的産品有幾十個,當然用抽象工廠模式一次替換全部最友善(這個工廠會替你用相應的工廠方法)是以說抽象工廠就像工廠,而工廠方法則像是工廠的一種産品生産線,
抽象工廠模式适合與如下的情況
多個抽象産品類,每個抽象産品類可以派生出多個具體産品類。 一個抽象工廠類,可以派生出多個具體工廠類。 每個具體工廠類可以建立多個具體産品類的執行個體。
下面附上抽象工廠的代碼
//單核産品類族
// 單核産品基類
class singlecore
{
public:
virtual void show( ) const = 0;
// 單核a
class singlecorea: public singlecore
void show( )const
std::cout<<"singlecore a"<<std::endl;
}
// 單核b
class singlecoreb: public singlecore
void show( ) const
std::cout<<"singlecore b"<<std::endl;
// 多核産品類族
// 多核産品類族基類
class multicore
{
public:
virtual void show( ) const = 0;
};
// 多核産品a
class multicorea : public multicore
void show() const
std::cout<<"multi core a"<<std::endl;
}
// 多核産品b
class multicoreb : public multicore
std::cout<<"multi core b"<<std::endl;
// 工廠
class factory
virtual singlecore* createsinglecore( ) = 0;
virtual multicore* createmulticore( ) = 0;
// 工廠a,專門用來生産a型号的處理器
class factorya :public factory
singlecore* createsinglecore( )
return new singlecorea( );
multicore* createmulticore( )
return new multicorea( );
// 工廠b,專門用來生産b型号的處理器
class factoryb : public factory
singlecore* createsinglecore()
return new singlecoreb( );
return new multicoreb( );
};
// 生産産品a系列的産品工廠
factorya *factorya = new factorya( );
factorya->createsinglecore( )->show( );
factorya->createmulticore( )->show( );
// 生産b系列的産品工廠
factoryb *factoryb = new factoryb( );
factoryb->createsinglecore( )->show( );
factoryb->createmulticore( )->show( );
本例采用c++設計,會造成記憶體洩漏,但是隻是為了講解一下工廠模式的基本思路,是以本例中不加以描述
但是在實際開發中我們可以采用在工廠類中添加生産産品連結清單,來避免記憶體洩漏。
轉載:http://blog.csdn.net/gatieme/article/details/17952033