1. 程式人生 > >java設計模式2.工廠模式

java設計模式2.工廠模式

工廠模式負責將大量擁有共同介面的類例項化,工廠模式可以動態決定將哪一個類例項化。

  • 簡單工廠模式

又稱靜態工廠模式,就是一個工廠類根據傳入的引數決定創建出哪一種產品類的例項。

  • 工廠類角色:工廠核心類,含有相關的業務判斷邏輯,在客戶端的直接呼叫下建立產品物件,往往由一個具體類實現。
  • 抽象產品角色:工廠建立的物件的父類或它們共同的介面,可以用一個介面或抽象類實現。
  • 具體產品角色:工廠所建立的物件的具體型別。

一個工廠類可以擁有多於一個的工廠方法,分別負責建立不同產品的物件。如果系統只有一個具體產品角色的話,可以省略掉抽象產品角色,有些情況下,工廠角色也可以由抽象產品角色扮演,如java.text.DataFormat。甚至三個角色全部合併,如在單例模式中,單例類具有一個靜態工廠方法提供自身例項,即是抽象角色也是具體產品角色,但此外它要求構造器私有。

簡單工廠模式的核心是工廠類,其含有必要的判斷邏輯,可以決定在什麼時候建立哪一個產品類的例項,而客戶端則可以免除直接建立產品物件的責任。但是當產品類有複雜的多層次等級結構時,工廠類只有它自己,這就是缺點,每次有新的產品加到系統中時,都必須修改工廠類。並且由於簡單工廠模式使用靜態工廠方法,無法由子類繼承,因此,工廠角色無法形成基於繼承的等級結構

  • 示例:DateFormat

如果看一下DateFormat就會發現,其實它是一個抽象類,但是卻提供了很多的靜態工廠方法,比如getDateInstance()為某種本地日期提供格式化,它由三個過載的方法構成。

抽象類不能有自己的例項,但是getDateInstance()並沒有呼叫DateFormat的構造子來提供自己的例項,而是返回自己子類SimpleDateFormat的一個例項,並將它宣告為DateFormat。這是最純正的多型性原則運用,如果getDateInstance()是一個非靜態的普通方法會怎樣呢,如果要使用,客戶端首先要獲得這個類或子類的例項,如果客戶端已取得子類的例項,又何必要這個工廠方法呢。DateFormat這樣做是利用超類型別將具體產品類的型別隱藏起來(里氏替換,面向抽象),其好處是提供了系統的可擴充套件性,如果將來有新的具體子類被加到系統中來,那麼工廠類可以將交給客戶端的物件換成新的子類的例項,而對客戶端沒有任何影響。

  • 工廠模式

工廠模式中,工廠類不再負責所有的產品建立,而是將具體的產品建立工作交給子類去完成。自己成為抽象工廠角色,僅負責給出具體子類工廠必須實現的介面,而負責判斷哪一個產品類應當被例項化。這種進一步抽象的結果,使工廠模式允許系統在不修改具體工廠角色的情況下,引進新的產品

  • 抽象工廠角色:工廠核心類,它是與應用程式無關的,任何在模式中建立物件的工廠類必須實現這個介面,通常由抽象類實現
  • 具體工廠角色:實現了工廠介面的具體類,含有與應用密切相關的業務邏輯,並受到應用程式的呼叫以建立產品物件。
  • 抽象產品角色:工廠所建立的物件的超類。
  • 具體產品角色:工廠所建立的物件的具體型別。

工廠模式的核心的是一個抽象工廠類,而簡單工廠模式的核心是一個具體類,工廠模式允許很多具體工廠類從抽象工廠類中將建立行為繼承下來,從而可以成為多個簡單工廠模式的綜合,進而推廣了簡單工廠模式。如果系統需要加入一個新的產品,那麼所需要的就是向系統中加入一個這個產品類及它所對應的工廠類。沒有必要修改客戶端,也沒有必要修改抽象工廠角色或者其他已有的具體工廠角色,對於新增的產品類而言,完全支援“開 - 閉”原則。

  • 示例:Collection

所有的java集合類都繼承了java.util.Collection介面。這個介面規定了所有集合類都要提供一個iterator()方法,返回一個 Iterator 型別例項。一個具體的java集合物件會通過這個iterator()方法返回一個具體的Iterator類,可以看出,這個iterator()方法就是一個工廠方法。類似的,List介面也給出兩個工廠方法,一個是繼承自Collection的iterator()方法,另一個是listIterator()方法,返回一個 ListIterator 型別例項。有趣的是ListIterator 繼承自Iterator 。

  • 示例:URL

建立一個URL物件很簡單,只要將一個合法的URL傳入到URL的構造子中即可URL url = new URL("http://www.baidu.com"); URL物件提供一個叫做openConnection的工廠方法,這個方法返回一個URLConnection物件。而URLConnection物件代表一個與遠端物件的連線。URLConnection是所有的代表應用系統與一個URL的連線物件的超類,使用URLConnection可以針對一個URL進行讀寫操作。顯然,URL使用了工廠模式,以一個工廠方法openConnection返還一個URLConnection型別的物件。由於URLConnection是一個抽象類,因此返還的只能是其子類的例項。

  • 抽象工廠模式

假設一個系統需要一些產品物件,而這些產品又屬於一個以上的產品等級結構。為了將消費這些產品物件的責任和建立這些產品物件的責任分割開來,可以引進抽象工廠模式。如果使用工廠模式處理的話,就必須有多個獨立的工廠族,如果這些產品族的等級結構相同,使用同一個工廠族也可以處理這些產品族的建立問題,其實只是對這些獨立的工廠族做了進一步的抽象。

#筆記內容參考《java與模式》