天道不一定酬所有勤
但是,天道只酬勤

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

新專題:設計模式,我會在博客(http://www.057299.live)及微信公眾號(hollischuang)同步更新,歡迎共同學習。

設計模式(五)——工廠方法模式中介紹了工廠方法模式。本文通過介紹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方法能得到不同的具體產品的實例。

collection-iterator-uml

JDBC數據庫開發

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

連接郵件服務器框架

如果需要設計一個連接郵件服務器的框架,那么就要考慮到連接郵件服務器有幾種方式: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()

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

參考資料

工廠方法模式

(全文完) 歡迎關注『Java之道』微信公眾號
贊(3)
如未加特殊說明,此網站文章均為原創,轉載必須注明出處。HollisChuang's Blog » 設計模式(六)——JDK中的那些工廠方法
分享到: 更多 (0)

評論 2

  • 昵稱 (必填)
  • 郵箱 (必填)
  • 網址
  1. #1

    我又來了,您高興嗎?!

    10273484884年前 (2016-04-15)回復
  2. #2

    java.lang.Proxy#newProxyInstance()這個不是簡單工廠模式嗎?

    小菜鳥7個月前 (08-28)回復

HollisChuang's Blog

聯系我關于我
大乐透复式返奖 4肖期期中无错版 11选5稳中两个算法 黑龙江11选5遗漏 安微11选5最新开奖 三肖期期中特准 上海11选五开奖结果一定牛 浙江11选五开奖结果 必中三头六尾中特 吉林省11选5开奖结果 六台宝典图库大全资料