1. 程式人生 > >工廠方法模式-Factory Method Pattern 工廠三兄弟之工廠方法模式(四):過載的工廠方法,工廠方法的隱藏,工廠方法模式總結

工廠方法模式-Factory Method Pattern 工廠三兄弟之工廠方法模式(四):過載的工廠方法,工廠方法的隱藏,工廠方法模式總結

5 過載的工廠方法

       Sunny公司開發人員通過進一步分析,發現可以通過多種方式來初始化日誌記錄器,例如可以為各種日誌記錄器提供預設實現;還可以為資料庫日誌記錄器提供資料庫連線字串,為檔案日誌記錄器提供檔案路徑;也可以將引數封裝在一個Object型別的物件中,通過Object物件將配置引數傳入工廠類。此時,可以提供一組過載的工廠方法,以不同的方式對產品物件進行建立。當然,對於同一個具體工廠而言,無論使用哪個工廠方法,建立的產品型別均要相同。如圖4所示:

過載的工廠方法結構圖

引入過載方法後,抽象工廠LoggerFactory的程式碼修改如下:

  1. interface
     LoggerFactory {  
  2.     public Logger createLogger();  
  3.     public Logger createLogger(String args);  
  4.     public Logger createLogger(Object obj);  
  5. }  

       具體工廠類DatabaseLoggerFactory程式碼修改如下:

  1. class DatabaseLoggerFactory implements LoggerFactory {  
  2.     public Logger createLogger() {  
  3.             //使用預設方式連線資料庫,程式碼省略
  4.             Logger logger = new DatabaseLogger();   
  5.             //初始化資料庫日誌記錄器,程式碼省略
  6.             return logger;  
  7.     }  
  8.     public Logger createLogger(String args) {  
  9.             //使用引數args作為連線字串來連線資料庫,程式碼省略
  10.             Logger logger = new DatabaseLogger();   
  11.             //初始化資料庫日誌記錄器,程式碼省略
  12.             return
     logger;  
  13.     }     
  14.     public Logger createLogger(Object obj) {  
  15.             //使用封裝在引數obj中的連線字串來連線資料庫,程式碼省略
  16.             Logger logger = new DatabaseLogger();   
  17.             //使用封裝在引數obj中的資料來初始化資料庫日誌記錄器,程式碼省略
  18.             return logger;  
  19.     }     
  20. }  
  21. //其他具體工廠類程式碼省略

       在抽象工廠中定義多個過載的工廠方法,在具體工廠中實現了這些工廠方法,這些方法可以包含不同的業務邏輯,以滿足對不同產品物件的需求。



6 工廠方法的隱藏

有時候,為了進一步簡化客戶端的使用,還可以對客戶端隱藏工廠方法,此時,在工廠類中將直接呼叫產品類的業務方法,客戶端無須呼叫工廠方法建立產品,直接通過工廠即可使用所建立的物件中的業務方法。

如果對客戶端隱藏工廠方法,日誌記錄器的結構圖將修改為圖5所示:

隱藏工廠方法後的日誌記錄器結構圖

在圖5中,抽象工廠類LoggerFactory的程式碼修改如下:

  1. //改為抽象類
  2. abstractclass LoggerFactory {  
  3.     //在工廠類中直接呼叫日誌記錄器類的業務方法writeLog()
  4.     publicvoid writeLog() {  
  5.         Logger logger = this.createLogger();  
  6.         logger.writeLog();  
  7.     }  
  8.     publicabstract Logger createLogger();    
  9. }  

       客戶端程式碼修改如下:

  1. class Client {  
  2.     publicstaticvoid main(String args[]) {  
  3.         LoggerFactory factory;  
  4.         factory = (LoggerFactory)XMLUtil.getBean();  
  5.         factory.writeLog(); //直接使用工廠物件來呼叫產品物件的業務方法
  6.     }  
  7. }  

       通過將業務方法的呼叫移入工廠類,可以直接使用工廠物件來呼叫產品物件的業務方法,客戶端無須直接使用工廠方法,在某些情況下我們也可以使用這種設計方案。

7 工廠方法模式總結

      工廠方法模式是簡單工廠模式的延伸,它繼承了簡單工廠模式的優點,同時還彌補了簡單工廠模式的不足。工廠方法模式是使用頻率最高的設計模式之一,是很多開源框架和API類庫的核心模式。

        1. 主要優點

       工廠方法模式的主要優點如下:

       (1) 在工廠方法模式中,工廠方法用來建立客戶所需要的產品,同時還向客戶隱藏了哪種具體產品類將被例項化這一細節,使用者只需要關心所需產品對應的工廠,無須關心建立細節,甚至無須知道具體產品類的類名。

       (2) 基於工廠角色和產品角色的多型性設計是工廠方法模式的關鍵。它能夠讓工廠可以自主確定建立何種產品物件,而如何建立這個物件的細節則完全封裝在具體工廠內部。工廠方法模式之所以又被稱為多型工廠模式,就正是因為所有的具體工廠類都具有同一抽象父類。

       (3) 使用工廠方法模式的另一個優點是在系統中加入新產品時,無須修改抽象工廠和抽象產品提供的介面,無須修改客戶端,也無須修改其他的具體工廠和具體產品,而只要新增一個具體工廠和具體產品就可以了,這樣,系統的可擴充套件性也就變得非常好,完全符合“開閉原則”。

      2. 主要缺點

     工廠方法模式的主要缺點如下:

      (1) 在新增新產品時,需要編寫新的具體產品類,而且還要提供與之對應的具體工廠類,系統中類的個數將成對增加,在一定程度上增加了系統的複雜度,有更多的類需要編譯和執行,會給系統帶來一些額外的開銷。

      (2) 由於考慮到系統的可擴充套件性,需要引入抽象層,在客戶端程式碼中均使用抽象層進行定義,增加了系統的抽象性和理解難度,且在實現時可能需要用到DOM、反射等技術,增加了系統的實現難度。

       3. 適用場景

       在以下情況下可以考慮使用工廠方法模式:

       (1) 客戶端不知道它所需要的物件的類。在工廠方法模式中,客戶端不需要知道具體產品類的類名,只需要知道所對應的工廠即可,具體的產品物件由具體工廠類建立,可將具體工廠類的類名儲存在配置檔案或資料庫中。

       (2) 抽象工廠類通過其子類來指定建立哪個物件。在工廠方法模式中,對於抽象工廠類只需要提供一個建立產品的介面,而由其子類來確定具體要建立的物件,利用面向物件的多型性和里氏代換原則,在程式執行時,子類物件將覆蓋父類物件,從而使得系統更容易擴充套件。

疑問

練習

使用工廠方法模式設計一個程式來讀取各種不同型別的圖片格式,針對每一種圖片格式都設計一個圖片讀取器,如GIF圖片讀取器用於讀取GIF格式的圖片、JPG圖片讀取器用於讀取JPG格式的圖片。需充分考慮系統的靈活性和可擴充套件性。