Java設計模式之工廠方法模式

上一篇講解了簡單工廠模式,下面講解簡單工廠模式的升級版,工廠方法模式。工廠方法模式(Factory Method Pattern)又稱爲工廠模式,也叫虛擬構造器(Virtual Constructor)模式或者多態工廠(Polymorphic Factory)模式,它屬於類創建型模式。在工廠方法模式中,工廠父類負責定義創建產品對象的公共接口,而工廠子類則負責生成具體的產品對象,這樣做的目的是將產品類的實例化操作延遲到工廠子類中完成,即通過工廠子類來確定究竟應該實例化哪一個具體產品類。

先看看工廠模式的UML圖:
這裏寫圖片描述
從上面UML圖可知,工廠模式中,有多個專門的工廠,每個工廠專門生產一種車,這些工廠都有一個共同的父類,客戶要什麼車,就讓相應的工廠生產車就OK了。下面看看代碼:

產品類:

abstract class BMW {
    public BMW(){
    }
}
public class BMW320Li extends BMW {
    public BMW320Li() {
        System.out.println("製造-->BMW320Li");
    }
}
public class BMW520Li extends BMW{
    public BMW520Li(){
        System.out.println("製造-->BMW520Li");
    }
}  

創建工廠類:

interface FactoryBMW {
    BMW createBMW();
}

public class FactoryBMW320Li implements FactoryBMW{
    @Override
    public BMW320Li createBMW() {
        return new BMW320Li();
    }
}

public class FactoryBMW520Li implements FactoryBMW {
    @Override
    public BMW520Li createBMW() {
        return new BMW520Li();
    }
}

客戶類:

public class Customer {
    public static void main(String[] args) {
        FactoryBMW320Li factoryBMW320Li = new FactoryBMW320Li();
        BMW320Li bmw320Li = factoryBMW320Li.createBMW();

        FactoryBMW520Li factoryBMW520Li = new FactoryBMW520Li();
        BMW520Li bmw523 = factoryBMW520Li.createBMW();
    }
}

工廠方法模式組成:

  1. 抽象工廠角色:這是工廠方法模式的核心,它與應用程序無關。是具體工廠角色必須實現的接口或者必須繼承的父類。在java中它由抽象類或者接口來實現。
  2. 具體工廠角色:它含有和具體業務邏輯有關的代碼。由應用程序調用以創建對應的具體產品的對象。
  3. 抽象產品角色:它是具體產品繼承的父類或者是實現的接口。在java中一般有抽象類或者接口來實現。
  4. 具體產品角色:具體工廠角色所創建的對象就是此角色的實例。在java中由具體的類來實現。

工廠方法模式是簡單工廠模式的進一步抽象和推廣。由於使用了面向對象的多態性,工廠方法模式保持了簡單工廠模式的優點,而且克服了它的缺點。工廠方法模式使用繼承自抽象工廠角色的多個子類來代替簡單工廠模式中的“上帝類”。這樣便分擔了對象承受的壓力;而且這樣使得結構變得靈活起來——當有新的產品產生時,只要按照抽象產品角色、抽象工廠角色提供的合同來生成,那麼就可以被客戶使用,而不必去修改任何已有的代碼。可以看出工廠角色的結構也是符合開閉原則的!

工廠方法模式的優點:

  1. 在工廠方法模式中,工廠方法用來創建客戶所需要的產品,同時還向客戶隱藏了哪種具體產品類將被實例化這一細節,用戶只需要關心所需產品對應的工廠,無須關心創建細節,甚至無須知道具體產品類的類名。
  2. 基於工廠角色和產品角色的多態性設計是工廠方法模式的關鍵。它能夠使工廠可以自主確定創建何種產品對象,而如何創建這個對象的細節則完全封裝在具體工廠內部。工廠方法模式之所以又被稱爲多態工廠模式,是因爲所有的具體工廠類都具有同一抽象父類。
  3. 使用工廠方法模式的另一個優點是在系統中加入新產品時,無須修改抽象工廠和抽象產品提供的接口,無須修改客戶端,也無須修改其他的具體工廠和具體產品,而只要添加一個具體工廠和具體產品就可以了。這樣,系統的可擴展性也就變得非常好,完全符合“開閉原則”。

工廠方法模式的缺點:

  1. 在添加新產品時,需要編寫新的具體產品類,而且還要提供與之對應的具體工廠類,系統中類的個數將成對增加,在一定程度上增加了系統的複雜度,有更多的類需要編譯和運行,會給系統帶來一些額外的開銷。
  2. 由於考慮到系統的可擴展性,需要引入抽象層,在客戶端代碼中均使用抽象層進行定義,增加了系統的抽象性和理解難度,且在實現時可能需要用到DOM、反射等技術,增加了系統的實現難度。

適用環境:

  1. 一個類不知道它所需要的對象的類:在工廠方法模式中,客戶端不需要知道具體產品類的類名,只需要知道所對應的工廠即可,具體的產品對象由具體工廠類創建;客戶端需要知道創建具體產品的工廠類。
  2. 一個類通過其子類來指定創建哪個對象:在工廠方法模式中,對於抽象工廠類只需要提供一個創建產品的接口,而由其子類來確定具體要創建的對象,利用面向對象的多態性和里氏代換原則,在程序運行時,子類對象將覆蓋父類對象,從而使得系統更容易擴展。
  3. 將創建對象的任務委託給多個工廠子類中的某一個,客戶端在使用時可以無須關心是哪一個工廠子類創建產品子類,需要時再動態指定,可將具體工廠類的類名存儲在配置文件或數據庫中。

模式擴展:

  1. 產品對象的重複使用:工廠對象將已經創建過的產品保存到一個集合(如數組、List等)中,然後根據客戶對產品的請求,對集合進行查詢。如果有滿足要求的產品對象,就直接將該產品返回客戶端;如果集合中沒有這樣的產品對象,那麼就創建一個新的滿足要求的產品對象,然後將這個對象在增加到集合中,再返回給客戶端。
  2. 多態性的喪失和模式的退化:如果工廠僅僅返回一個具體產品對象,便違背了工廠方法的用意,發生退化,此時就不再是工廠方法模式了。一般來說,工廠對象應當有一個抽象的父類型,如果工廠等級結構中只有一個具體工廠類的話,抽象工廠就可以省略,也將發生了退化。當只有一個具體工廠,在具體工廠中可以創建所有的產品對象,並且工廠方法設計爲靜態方法時,工廠方法模式就退化成簡單工廠模式。

未完待續

更多精彩Android技術可以關注我們的微信公衆號,掃一掃下方的二維碼或搜索關注公共號: Android老鳥


這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章