設計模式(六)——JDK中的那些工廠方法

l2wonxgc 8年前發布 | 14K 次閱讀 工廠模式 JDK

設計模式(五)——工廠方法模式 中介紹了工廠方法模式。本文通過介紹JDK源碼中用到的工廠方法,在上篇文章的基礎上深入理解一下工廠方法。

再談工廠方法

設計模式(五)——工廠方法模式 中用整篇介紹了工廠方法模式。為什么要再談呢?因為很多人走進了一個誤區。認為工廠方法模式就是要嚴格包含抽象產品、具體產品、抽象工廠和具體工廠等角色。其實并不是這樣的。

有時候也會創建不使用多態性創建對象的工廠方法,以得到使用工廠方法的其他好處。

如果拋開設計模式的范疇,“工廠方法”這個詞也可以指 作為“工廠”的方法 ,這個方法的主要目的就是創建對象,而這個方法不一定在單獨的工廠類中。這些方法通常作為靜態方法,定義在方法所實例化的類中。

每個工廠方法都有特定的名稱。在許多面向對象的編程語言中,構造方法必須和它所在的類具有相同的名稱,這樣的話,如果有多種創建對象的方式(重載)就可能導致歧義。工廠方法沒有這種限制,所以可以具有描述性的名稱。舉例來說,根據兩個實數創建一個復數,而這兩個實數表示直角坐標或極坐標,如果使用工廠方法,方法的含義就非常清晰了。當工廠方法起到這種消除歧義的作用時,構造方法常常被設置為私有方法,從而強制客戶端代碼使用工廠方法創建對象。

class Complex {
     public static Complex fromCartesianFactory(double real, double imaginary) {
         return new Complex(real, imaginary);
     }
     public static Complex fromPolarFactory(double modulus, double angle) {
         return new Complex(modulus * cos(angle), modulus * sin(angle));
     }
     private Complex(double a, double b) {
         //...
     }
}

Complex product = Complex.fromPolarFactory(1, pi);

上面的代碼也可以叫做使用了工廠方法模式。同樣是定義了一個工廠方法,方法的作用就是生成一個新的對象。

JDK中的工廠方法模式

看過前面的介紹和上一篇文章的介紹,相信讀者對工廠方法有了一定的認識,那么能不能試著回答這樣一個問題:什么情況下應該使用工廠方法模式?

其實這個問題很簡單。很多時候我們在自己的代碼中會不自覺的會使用到工廠方法模式。考慮以下情況:

創建對象需要大量重復的代碼。

創建對象需要訪問某些信息,而這些信息不應該包含在復合類中。

創建對象的生命周期必須集中管理,以保證在整個程序中具有一致的行為。

遇到上面的情況時,你是不是會”很自覺”的把創建對象的代碼封裝到一個方法中呢?這個方法就是工廠方法。其實這就是工廠方法的思想。

在JDK中,也有很多使用工廠方法模式的代碼。下面就介紹幾個典型的用法。

Collection中的iterator方法

java.util.Collection 接口中定義了一個抽象的 iterator() 方法,該方法就是一個工廠方法。

對于 iterator() 方法來說 Collection 就是一個根抽象工廠,下面還有 List 等接口作為抽象工廠,再往下有 ArrayList 等具體工廠。

java.util.Iterator 接口是根抽象產品,下面有 ListIterator 等抽象產品,還有 ArrayListIterator 等作為具體產品。

使用不同的具體工廠類中的 iterator 方法能得到不同的具體產品的實例。

JDBC數據庫開發

在使用 JDBC 進行數據庫開發時,如果數據庫由MySQL改為Oracle或其他,則只需要改一下數據庫驅動名稱就可以,其他都不用修改(前提是使用的都是標準SQL語句)。或者在Hibernate框架中,更換數據庫方言也是類似道理。

連接郵件服務器框架

如果需要設計一個連接郵件服務器的框架,那么就要考慮到連接郵件服務器有幾種方式: POP3 、 SMTP 、 HTTP 。就可以定義一個連接郵件服務器接口,在此接口中定義一些對郵件操作的接口方法,把這三種連接方式封裝成產品類,實現接口中定義的抽象方法。再定義抽象工廠和具體工廠,當選擇不同的工廠時,對應到產生相應的連接郵件產品對象。采用這種工廠方法模式的設計,就可以做到良好的擴展性。比如某些郵件服務器提供了WebService接口,只需要增加一個產品類和工廠類就可以了,而不需要修改原來代碼。

其他工廠方法

除上面介紹的典型的使用工廠方法模式的用法外,在JDK中還有幾處使用了工廠方法來創建對象。其中包括:

java.lang.Proxy#newProxyInstance()
java.lang.Object#toString()
java.lang.Class#newInstance()
java.lang.reflect.Array#newInstance()
java.lang.reflect.Constructor#newInstance()
java.lang.Boolean#valueOf(String)
java.lang.Class#forName()

讀者感興趣可以找出來看一看,這些方法都是用于返回具體對象。上面大部分方法都和反射有關,因為反射創建對象的過程比較復雜,封裝成工廠方法更易于使用。

參考資料

工廠方法模式

(全文完)

來自: http://www.hollischuang.com/archives/1408

 本文由用戶 l2wonxgc 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!