工廠方法模式

2021-08-13 17:34:59 字數 3590 閱讀 9425

概述在軟體系統中,經常面臨著「某個物件」的建立工作,由於需求的變化,這個物件的具體實現經常面臨著劇烈的變化,但是它卻擁有比較穩定的介面。如何應對這種變化?提供一種封裝機制來隔離出「這個易變物件」的變化,從而保持系統中「其它依賴該物件的物件」不隨著需求的改變而改變?

這就是要說的factory method模式了。

意圖定義乙個使用者建立物件的介面,讓子類決定例項化哪乙個類。factory method使乙個類的例項化延遲到其子類。

結構圖生活中的例子

工廠方法定義乙個用於建立物件的介面,但是讓子類決定例項化哪個類。壓注成型演示了這種模式。塑料玩具製造商加工塑料粉,將塑料注入到希望形狀的模具中。

玩具的類別(車,人物等等)是由模具決定的。

工廠方法解說

在工廠方法模式中,核心的工廠類不再負責所有產品的建立,而是將具體建立工作交給子類去做。這個核心類僅僅負責給出具體工廠必須實現的介面,而不接觸哪乙個產品類被例項化這種細節。這使得工廠方法模式可以允許系統在不修改工廠角色的情況下引進新產品。

在factory method模式中,工廠類與產品類往往具有平行的等級結構,它們之間一一對應。

現在我們考慮乙個日誌記錄的例子(這裡我們只是為了說明factory method模式,實際專案中的日誌記錄不會這麼去做,也要比這複雜一些)。假定我們要設計日誌記錄的類,支援記錄的方法有filelog和eventlog兩種方式。在這裡我們先不談設計模式,那麼這個日誌記錄的類就很好實現了:

1///

2///日誌記錄類

3///

4publicclasslog511

12publicvoidwritefile()

1316

17publicvoidwrite(stringlogtype)

1832}

33}34

這樣的程式結構顯然不能符合我們的要求,如果我們增加一種新的日誌記錄的方式databaselog,那就要修改log類,隨著記錄方式的變化,switch語句在不斷的變化,這樣就引起了整個應用程式的不穩定,進一步分析上面的**,發現對於eventlog和filelog是兩種完全不同的記錄方式,它們之間不應該存在必然的聯絡,而應該把它們分別作為單獨的物件來對待。

1///

2///eventlog類具體產品類(concrete product)

3///

4publicclasseventlog

510}

1112///

13///filelog類具體產品類(concrete product)

14///

15publicclassfilelog

1621}

22進一步抽象,為它們抽象出乙個共同的父類,結構圖如下:

實現**:

1///

2///log 抽象產品類(abstract product) 或者說為一類產品物件什麼乙個介面

3///

4publicabstractclasslog58

此時eventlog和filelog類的**應該如下:

1///

2///eventlog類

3///

4publicclasseventlog:log 具體產品類(concrete product)將被具體工廠生產的物件

510}

11///

12///filelog類

13///

14publicclassfilelog:log具體產品類(concrete product)

1520}

21此時我們再看增加新的記錄日誌方式databaselog的時候,需要做哪些事情?只需要增加乙個繼承父類log的子類來實現,而無需再去修改eventlog和filelog類,這樣的設計滿足了類之間的層次關係,又很好的符合了物件導向設計中的單一職責原則,每乙個類都只負責一件具體的事情。到這裡似乎我們的設計很完美了,事實上我們還沒有看客戶程式如何去呼叫。

在應用程式中,我們要使用某一種日誌記錄方式,也許會用到如下這樣的語句:

eventlogeventlog=neweventlog();

eventlog.write();

當日誌記錄的方式從eventlog變化為filelog,我們就得修改所有程式**中出現上面語句的部分,這樣的工作量是可想而知的。此時就需要解耦具體的日誌記錄方式和應用程式。這就要引入factory method模式了,每乙個日誌記錄的物件就是工廠所生成的產品,既然有兩種記錄方式,那就需要兩個不同的工廠去生產了,**如下:

1///

2///eventfactory類

3///

4publicclasseventfactory

510}

11///

12///filefactory類

13///

14publicclassfilefactory

1520}

21這兩個工廠和具體的產品之間是平行的結構,並一一對應,並在它們的基礎上抽象出乙個公用的介面,結構圖如下:

實現**如下:

1///

2///logfactory類抽象工廠(abstract factory)宣告乙個建立抽象產品的物件的操作介面

3///

4publicabstractclasslogfactory 58

此時兩個具體工廠的**應該如下:

1///

2///eventfactory類具體工廠(concrete factory)實現建立具體產品物件的操作

3///

4publicclasseventfactory:logfactory

510}

11///

12///filefactory類

13///

14publicclassfilefactory:logfactory

1520}

21這樣通過工廠方法模式我們把上面那物件建立工作封裝在了工廠中,此時我們似乎完成了整個factory method的過程。這樣達到了我們應用程式和具體日誌記錄物件之間解耦的目的了嗎?看一下此時客戶端程式**:

1///

2///app類

3///

4publicclassapp

514}

15在客戶程式中,我們有效地避免了具體產品物件和應用程式之間的耦合,可是我們也看到,增加了具體工廠物件和應用程式之間的耦合。那這樣究竟帶來什麼好處呢?我們知道,在應用程式中,log物件的建立是頻繁的,在這裡我們可以把

logfactory factory = new eventfactory();

這句話放在乙個類模組中,任何需要用到log物件的地方仍然不變。要是換一種日誌記錄方式,只要修改一處為:

logfactory factory = new filefactory();

其餘的任何地方我們都不需要去修改。有人會說那還是修改**,其實在開發中我們很難避免修改,但是我們可以盡量做到只修改一處。

其實利用.net的特性,我們可以避免這種不必要的修改。下面我們利用.

net中的反射機制來進一步修改我們的程式,這時就要用到配置檔案了,如果我們想使用哪一種日誌記錄方式,則在相應的配置檔案中設定如下:12

34此時客戶端**如下:

1///

2///app類

3///

4publicclassapp

516}17

工廠方法 Factory Method 模式

一 工廠方法 factory method 模式 工廠方法 factorymethod 模式是類的建立模式,其用意是定義乙個建立產品物件的工廠介面,將實際建立工作推遲到子類中。工廠方法模式是簡單工廠模式的進一步抽象和推廣。由於使用了多型性,工廠方法模式保持了簡單工廠模式的優點,而且克服了它的缺點。在...

簡單工廠模式,工廠方法模式和抽象工廠模式的異同

簡單工廠模式,工廠方法模式和抽象工廠模式都是屬於建立型設計模式,這三種建立型模式都不需要知道具體類。我們掌握一種思想,就是在建立乙個物件時,需要把容易發生變化的地方給封裝起來,來控制變化 變化,封裝 以適應客戶的變動,專案的擴充套件。用這三種設計模式都可以實現,那究竟這三種設計模式有什麼異同呢?下面...

抽象工廠模式

抽象工廠模式是所有形態的工廠模式中最為抽象和最具一般性的一種形態。抽象工廠模式是指當有多個抽象角色時,使用的一種工廠模式。抽象工廠模式可以向具體產品提供乙個介面,使客戶端在不必指定產品的具體的情況下,建立多個產品族中的產品物件。任何接受父型別的地方,都應當能夠接受子型別。因此,實際上系統所需要的,僅...