工廠方法(factorymethod)模式是類的建立模式,其用意是定義乙個建立產品物件的工廠介面,將實際建立工作推遲到子類中。
工廠方法模式是簡單工廠模式的進一步抽象和推廣。由於使用了多型性,工廠方法模式保持了簡單工廠模式的優點,而且克服了它的缺點。
在工廠方法模式中,核心的工廠類不再負責所有產品的建立,而是將具體建立工作交給子類去做。這個核心類僅僅負責給出具體工廠必須實現的介面,而不接觸哪乙個產品類被例項化這種細節。這使得工廠方法模式可以允許系統在不修改工廠角色的情況下引進新產品。
在factory method模式中,工廠類與產品類往往具有平行的等級結構,它們之間一一對應。
抽象工廠(creator)角色:是工廠方法模式的核心,與應用程式無關。任何在模式中建立的物件的工廠類必須實現這個介面。
具體工廠(concrete creator)角色:這是實現抽象工廠介面的具體工廠類,包含與應用程式密切相關的邏輯,並且受到應用程式呼叫以建立產品物件。在上圖中有兩個這樣的角色:bulbcreator與tubecreator。
抽象產品(product)角色:工廠方法模式所建立的物件的超型別,也就是產品物件的共同父類或共同擁有的介面。在上圖中,這個角色是light。
具體產品(concrete product)角色:這個角色實現了抽象產品角色所定義的介面。某具體產品有專門的具體工廠建立,它們之間往往一一對應。
三、 程式舉例:對於工廠模式來說,要求高層模組變化相對較慢,底層模組變化相對較快。這樣符合設計模式中的依賴倒置原則——高層模組不依賴於底層模組。換句話說,軟體設計是要劃分易變部分和穩定部分。
剛開始接觸設計模式時就常常聽到同事提起工廠模式,那時也看過一些人寫的blog,但是往往把注意力放在**的編寫上。在這段時間的學習中慢慢體會到設計模式是用來解決一類問題,而不是某些固定的**片段。換句話說是解決問題的思想。設計模式可以解決模組的耦合關係,可以解決因需求變動帶來的問題。程式在第一次編寫時,各個模組之間可能是緊耦合,但是經過**重構,可以將模組之間變為松耦合。當然,我覺得我們也可以在軟體設計之初把變化考慮到其中,對於業務型軟體設計,在了解需求後,可以盡可能將其分出主次關係。也就是主體與枝節的關係。如下圖
對於工廠模式來說,要求高層模組變化相對較慢,底層模組變化相對較快。這樣符合設計模式中的依賴倒置原則——高層模組不依賴於底層模組。換句話說,軟體設計是要劃分易變部分和穩定部分。這樣在一些枝節問題發生變化時,主幹不用變化。如果是緊耦合狀態,有可能造成乙個地方變化,連帶著很多地方要發生變化。
工廠模式要解決的是「某個物件」的建立工作,由於需求的變化,這個物件常常面臨著劇烈的變化,但是這個物件擁有的介面相對穩定。也就是說:枝節常常發生變化,但是枝節與主幹的介面相對穩定。
《設計模式》中是這樣說明:定義乙個用於建立物件的介面,讓子類決定例項化那個類。factorymethod使得乙個類的例項化延遲到子類。
現在看這句話可能有些不明白,我們一會再來分析一下。先來看看工廠模式的大體結構。如下圖:
工廠方法模式uml圖
下面我們來具體實現一下**,首先,我們需要兩個基類,乙個是car的,乙個是factory的。factory型別的作用是構建car的物件。**如下:
[c-sharp]view plaincopy
public
abstract
class abstractcar
public
abstract
class abstractfactory
下面,我們來做乙個bmw的實現**:
public
class bmwcar:abstractcar
public
override
string stop()
public
override
string accelerate()
public
override
string decelerate()
} public
class bmwfactory:abstractfactory
} 這樣我們就可以在客戶端程式得到乙個bmw的例項,並使用它的方法:
class class1
public
static abstractcar createcarfunc(abstractfactory factory)
} 在客戶端程式中,我們abstractfactory的物件來得到car的物件
結果如下:
bmw run
bmw stop
bmw accelerate
bmw decalerate
如果我們需求變了,現在要bora的物件,那末,我們首先要對程式作一下擴充套件,先加入boar的car類和factory類,**如下:
public
class boracar:abstractcar
public
override
string stop()
public
override
string accelerate()
public
override
string decelerate()
} public
class borafactory:abstractfactory
} 在客戶端程式中,我們只要稍作修改,將bmwfactory的例項化變為borafactory的例項化就可以,**如下:
class class1
public
static abstractcar createcarfunc(abstractfactory factory)
}
得到的結果是:
bora run
bora stop
bora accelerate
bora decelerate
factory method的幾個要點:
1、factory method模式主要用於隔離類物件的使用者和具體型別之間的耦合關係。面對乙個經常變化的具體型別,緊耦合關係會導致軟體的脆弱。
2、factory method模式通過物件導向的手法,將所要建立的物件工作延遲到子類,從而實現一種擴充套件的策略,較好的解決了這種緊耦合關係。工廠方法的活動序列圖
活動過程包括:
客戶端建立bulbcreator物件,客戶端持有此物件的型別是creator,而實際型別是bulbcreator。然後客戶端呼叫bulbcreator的factory方法,之後bulbcreator呼叫bulblight的建構函式創造出產品bulblight物件。
工廠方法模式與簡單工廠模式再結構上的不同不是很明顯。工廠方法類的核心是乙個抽象工廠類,而簡單工廠模式把核心放在乙個具體類上。
工廠方法模式之所以有乙個別名叫多型性工廠模式是因為具體工廠類都有共同的介面,或者有共同的抽象父類。
當系統擴充套件需要新增新的產品物件時,僅僅需要新增乙個具體物件以及乙個具體工廠物件,原有工廠物件不需要進行任何修改,也不需要修改客戶端,很好的符合了"開放-封閉"原則。而簡單工廠模式在新增新產品物件後不得不修改工廠方法,擴充套件性不好。
工廠方法模式退化後可以演變成簡單工廠模式。
使用介面或抽象類
抽象工廠角色和抽象場頻角色都可以選擇由介面或抽象類實現。
使用多個工廠方法
抽象工廠角色可以規定出多於乙個的工廠方法,從而使具體工廠角色實現這些不同的工廠方法,這些方法可以提供不同的商業邏輯,以滿足提供不同的產品物件的任務。
產品的迴圈使用
工廠方法總是呼叫產品類的建構函式以建立乙個新的產品例項,然後將這個例項提供給客戶端。而在實際情形中,工廠方法所做的事情可以相當複雜。
乙個常見的複雜邏輯就是迴圈使用產品物件。工廠物件將已經建立過的產品登記到乙個聚集中,然後根據客戶所請求的產品狀態,向聚集查詢。如果有滿足要求的產品物件,就直接將產品返回客戶端;如果聚集中沒有這樣的產品物件,那麼就建立乙個新的滿足要求的產品物件,然後將這個物件登記到聚集中,再返還給客戶端。"享元模式(flyweight pattern)"就是這樣乙個模式。
多型性的喪失和模式的退化
乙個工廠方法模式的實現依賴於工廠角色和產品角色的多型性。在有些情況下,這個模式可以出現退化。
工廠方法返回的型別應當是抽象型別,而不是具體型別。呼叫工廠方法的客戶端應當依賴抽象產品程式設計,而不是具體產品。如果工廠僅僅返回乙個具體產品物件,便違背了工廠方法的用意,發生退化,這時就不再是工廠模式了。
工廠的等級結構:工廠物件應當有乙個抽象的超型別。如果等級結構中只有乙個具體工廠類的話,抽象工廠就可以省略,發生了退化。
與工廠方法模式有關的模式還包括:
模板方法模式、mvc模式、享元模式、備忘錄模式
工廠模式(Factory Method
意圖 工廠方法模式 factory method pattern 工廠方法模式又稱為 工廠模式 也叫虛擬構造器 virtual constructor 模式或者 多型模式 屬於類的建立型模式。在工廠方法模式中,父類負責定義建立物件 的公共介面,而子類則負責生成具體的物件,這樣做的目的是將類的例項化操...
Factory Method(工廠模式)
定義了乙個建立物件的介面,但由子類決定要例項化的類是哪乙個。工廠方法讓類把例項化推遲到子類。將產品的 實現 從 使用 中解耦 1.當乙個類不知道它所必須建立的物件的類的時候 2.當乙個類希望由它的子類來指定它所建立的物件的時候 3.當想將建立物件的職責委託給多個幫助子類中的某乙個,並且希望將哪乙個幫...
工廠方法(Factory Method)
為建立的物件定義乙個抽象類,雖然該抽象類負責建立物件,但由它的實現類決定哪個類需要例項化。即不在由單個工廠類決定應該例項化哪個子類。工廠類會將這決定推遲到每個子類中完成。product page 定義乙個由工廠方法例項化的物件介面。concreteproduct skillspage,educati...