天天看點

設計模式(19):建立型-簡單工廠模式(Simple Factory)及工廠方法模式(Factory Method)一.簡單工廠模式(Simple Factory)二.工廠方法模式(Factory Method)三.日志記錄器的設計四.重載的工廠方法五.工廠方法的隐藏六.工廠方法模式總結

設計模式(Design pattern)是一套被反複使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了可重用代碼、讓代碼更容易被他人了解、保證代碼可靠性。 毫無疑問,設計模式于己于他人于系統都是多赢的;設計模式使代碼編制真正工程化;設計模式是軟體工程的基石脈絡,如同大廈的結構一樣。

設計模式分為三種類型,共23種。

建立型模式(5):單例模式、抽象工廠模式、建造者模式、工廠模式、原型模式。

結構型模式(7):擴充卡模式、橋接模式、裝飾模式、組合模式、外觀模式、享元模式、代理模式。

行為型模式(11):(父子類)政策模式、模版方法模式,(兩個類)觀察者模式、疊代器模式、職責鍊模式、指令模式,(類的狀态)狀态模式、備忘錄模式,(中間類) 通路者模式、中介者模式、解釋器模式。

  工廠模式是最常用的一類建立型設計模式,通常我們所說的工廠模式是指工廠方法模式,它也是使用頻率最高的工廠模式。而簡單工廠模式是工廠方法模式的“小弟”,它不屬于GoF 23種設計模式,但在軟體開發中應用也較為頻繁,通常将它作為學習其他工廠模式的入門。此外,工廠方法模式還有一位“大哥”——抽象工廠模式。這三種工廠模式各具特色,難度也逐個加大,在軟體開發中它們都得到了廣泛的應用,成為面向對象軟體中常用的建立對象的工具。

一.簡單工廠模式(Simple Factory)

  簡單工廠模式并不屬于GoF 23個經典設計模式,但通常将它作為學習其他工廠模式的基礎,它的設計思想很簡單,其基本流程如下:

  首先将需要建立的各種不同對象(例如各種不同的Chart對象)的相關代碼封裝到不同的類中,這些類稱為具體産品類,而将它們公共的代碼進行抽象和提取後封裝在一個抽象産品類中,每一個具體産品類都是抽象産品類的子類;然後提供一個工廠類用于建立各種産品,在工廠類中提供一個建立産品的工廠方法,該方法可以根據所傳入的參數不同建立不同的具體産品對象;用戶端隻需調用工廠類的工廠方法并傳入相應的參數即可得到一個産品對象。

定義

  簡單工廠模式(Simple Factory Pattern):定義一個工廠類,它可以根據參數的不同傳回不同類的執行個體,被建立的執行個體通常都具有共同的父類。因為在簡單工廠模式中用于建立執行個體的方法是靜态(static)方法,是以簡單工廠模式又被稱為靜态工廠方法(Static Factory Method)模式,它屬于類建立型模式。

  簡單工廠模式的要點在于:當你需要什麼,隻需要傳入一個正确的參數,就可以擷取你所需要的對象,而無須知道其建立細節。簡單工廠模式結構比較簡單,其核心是工廠類的設計,其結構如圖1所示:

設計模式(19):建立型-簡單工廠模式(Simple Factory)及工廠方法模式(Factory Method)一.簡單工廠模式(Simple Factory)二.工廠方法模式(Factory Method)三.日志記錄器的設計四.重載的工廠方法五.工廠方法的隐藏六.工廠方法模式總結

結構

在簡單工廠模式結構圖中包含如下幾個角色:

  • Factory(工廠角色):工廠角色即工廠類,它是簡單工廠模式的核心,負責實作建立所有産品執行個體的内部邏輯;工廠類可以被外界直接調用,建立所需的産品對象;在工廠類中提供了靜态的工廠方法factoryMethod(),它的傳回類型為抽象産品類型Product。
  • Product(抽象産品角色):它是工廠類所建立的所有對象的父類,封裝了各種産品對象的公有方法,它的引入将提高系統的靈活性,使得在工廠類中隻需定義一個通用的工廠方法,因為所有建立的具體産品對象都是其子類對象。
  • ConcreteProduct(具體産品角色):它是簡單工廠模式的建立目标,所有被建立的對象都充當這個角色的某個具體類的執行個體。每一個具體産品角色都繼承了抽象産品角色,需要實作在抽象産品中聲明的抽象方法。

      在簡單工廠模式中,用戶端通過工廠類來建立一個産品類的執行個體,而無須直接使用new關鍵字來建立對象,它是工廠模式家族中最簡單的一員。

實作

  在使用簡單工廠模式時,首先需要對産品類進行重構,不能設計一個包羅萬象的産品類,而需根據實際情況設計一個産品層次結構,将所有産品類公共的代碼移至抽象産品類,并在抽象産品類中聲明一些抽象方法,以供不同的具體産品類來實作,典型的抽象産品類代碼如下所示:

  

public abstract class Product {    
    //所有産品類的公共業務方法    
    public void methodSame() {    
        //公共方法的實作    
    }    

    //聲明抽象業務方法    
    public abstract void methodDiff();    
}   
           

在具體産品類中實作了抽象産品類中聲明的抽象業務方法,不同的具體産品類可以提供不同的實作,典型的具體産品類代碼如下所示:

public class ConcreteProduct extends Product {    
    //實作業務方法    
    public void methodDiff() {    
        //業務方法的實作    
    }    
}    
           

簡單工廠模式的核心是工廠類,在沒有工廠類之前,用戶端一般會使用new關鍵字來直接建立産品對象,而在引入工廠類之後,用戶端可以通過工廠類來建立産品,在簡單工廠模式中,工廠類提供了一個靜态工廠方法供用戶端使用,根據所傳入的參數不同可以建立不同的産品對象,典型的工廠類代碼如下所示:

public class Factory {    
    //靜态工廠方法    
    public static Product getProduct(String arg) {    
        Product product = null;    
        if (arg.equalsIgnoreCase("A")) {    
            product = new ConcreteProductA();    
            //初始化設定product    
        }    
        else if (arg.equalsIgnoreCase("B")) {    
            product = new ConcreteProductB();    
            //初始化設定product    
        }    
        return product;    
    }    
}    
           

在用戶端代碼中,我們通過調用工廠類的工廠方法即可得到産品對象,典型代碼如下所示:

public class Client {    
    public static void main(String args[]) {    
        Product product;     
        product = Factory.getProduct("A"); //通過工廠類建立産品對象    
        product.methodSame();    
        product.methodDiff();    
    }    
}   
           

圖表庫的設計

Sunny軟體公司欲基于Java語言開發一套圖表庫,該圖表庫可以為應用系統提供各種不同外觀的圖表,例如柱狀圖、餅狀圖、折線圖等。Sunny軟體公司圖表庫設計人員希望為應用系統開發人員提供一套靈活易用的圖表庫,而且可以較為友善地對圖表庫進行擴充,以便能夠在将來增加一些新類型的圖表。

為了将Chart類的職責分離,同時将Chart對象的建立和使用分離,Sunny軟體公司開發人員決定使用簡單工廠模式對圖表庫進行重構,重構後的結構如圖所示:

設計模式(19):建立型-簡單工廠模式(Simple Factory)及工廠方法模式(Factory Method)一.簡單工廠模式(Simple Factory)二.工廠方法模式(Factory Method)三.日志記錄器的設計四.重載的工廠方法五.工廠方法的隐藏六.工廠方法模式總結

在圖中,Chart接口充當抽象産品類,其子類HistogramChart、PieChart和LineChart充當具體産品類,ChartFactory充當工廠類。完整代碼如下所示:

//抽象圖表接口:抽象産品類    
public interface Chart {    
    public void display();    
}    

//柱狀圖類:具體産品類    
class HistogramChart implements Chart {    
    public HistogramChart() {    
        System.out.println("建立柱狀圖!");    
    }    

    public void display() {    
        System.out.println("顯示柱狀圖!");    
    }    
}    

//餅狀圖類:具體産品類    
class PieChart implements Chart {    
    public PieChart() {    
        System.out.println("建立餅狀圖!");    
    }    

    public void display() {    
        System.out.println("顯示餅狀圖!");    
    }    
}    

//折線圖類:具體産品類    
class LineChart implements Chart {    
    public LineChart() {    
        System.out.println("建立折線圖!");    
    }    

    public void display() {    
        System.out.println("顯示折線圖!");    
    }    
}    

//圖表工廠類:工廠類    
public class ChartFactory {    
    //靜态工廠方法    
    public static Chart getChart(String type) {    
        Chart chart = null;    
        if (type.equalsIgnoreCase("histogram")) {    
            chart = new HistogramChart();    
            System.out.println("初始化設定柱狀圖!");    
        }    
        else if (type.equalsIgnoreCase("pie")) {    
            chart = new PieChart();    
            System.out.println("初始化設定餅狀圖!");    
        }    
        else if (type.equalsIgnoreCase("line")) {    
            chart = new LineChart();    
            System.out.println("初始化設定折線圖!");                
        }    
        return chart;    
    }    
}   
           

編寫如下用戶端測試代碼:

public class Client {    
    public static void main(String args[]) {  
        //通過靜态工廠方法建立産品      
        Chart chart = ChartFactory.getChart("histogram"); 
        chart.display();    
    }    
}   
           

輸出結果如下:

建立柱狀圖!
初始化設定柱狀圖!
顯示柱狀圖!
           

  在用戶端測試類中,我們使用工廠類的靜态工廠方法建立産品對象,如果需要更換産品,隻需修改靜态工廠方法中的參數即可。

模式的簡化

  有時候,為了簡化簡單工廠模式,我們可以将抽象産品類和工廠類合并,将靜态工廠方法移至抽象産品類中,如圖3所示:

設計模式(19):建立型-簡單工廠模式(Simple Factory)及工廠方法模式(Factory Method)一.簡單工廠模式(Simple Factory)二.工廠方法模式(Factory Method)三.日志記錄器的設計四.重載的工廠方法五.工廠方法的隐藏六.工廠方法模式總結

  在圖中,用戶端可以通過産品父類的靜态工廠方法,根據參數的不同建立不同類型的産品子類對象,這種做法在JDK等類庫和架構中也廣泛存在。

模式總結

簡單工廠模式提供了專門的工廠類用于建立對象,将對象的建立和對象的使用分離開,它作為一種最簡單的工廠模式在軟體開發中得到了較為廣泛的應用。

1. 主要優點

(1) 工廠類包含必要的判斷邏輯,可以決定在什麼時候建立哪一個産品類的執行個體,用戶端可以免除直接建立産品對象的職責,而僅僅“消費”産品,簡單工廠模式實作了對象建立和使用的分離。

(2) 用戶端無須知道所建立的具體産品類的類名,隻需要知道具體産品類所對應的參數即可,對于一些複雜的類名,通過簡單工廠模式可以在一定程度減少使用者的記憶量。

(3) 通過引入配置檔案,可以在不修改任何用戶端代碼的情況下更換和增加新的具體産品類,在一定程度上提高了系統的靈活性。

2. 主要缺點

(1) 由于工廠類集中了所有産品的建立邏輯,職責過重,一旦不能正常工作,整個系統都要受到影響。

(2) 使用簡單工廠模式勢必會增加系統中類的個數(引入了新的工廠類),增加了系統的複雜度和了解難度。

(3) 系統擴充困難,一旦添加新産品就不得不修改工廠邏輯,在産品類型較多時,有可能造成工廠邏輯過于複雜,不利于系統的擴充和維護。

(4) 簡單工廠模式由于使用了靜态工廠方法,造成工廠角色無法形成基于繼承的等級結構。

3. 适用場景

在以下情況下可以考慮使用簡單工廠模式:

(1) 工廠類負責建立的對象比較少,由于建立的對象較少,不會造成工廠方法中的業務邏輯太過複雜。

(2) 用戶端隻知道傳入工廠類的參數,對于如何建立對象并不關心。

練習

使用簡單工廠模式設計一個可以建立不同幾何形狀(如圓形、方形和三角形等)的繪圖工具,每個幾何圖形都具有繪制draw()和擦除erase()兩個方法,要求在繪制不支援的幾何圖形時,提示一個UnSupportedShapeException。

二.工廠方法模式(Factory Method)

  在簡單工廠模式中隻提供一個工廠類,該工廠類處于對産品類進行執行個體化的中心位置,它需要知道每一個産品對象的建立細節,并決定何時執行個體化哪一個産品類。簡單工廠模式最大的缺點是當有新産品要加入到系統中時,必須修改工廠類,需要在其中加入必要的業務邏輯,這違背了“開閉原則”。此外,在簡單工廠模式中,所有的産品都由同一個工廠建立,工廠類職責較重,業務邏輯較為複雜,具體産品與工廠類之間的耦合度高,嚴重影響了系統的靈活性和擴充性,而工廠方法模式則可以很好地解決這一問題,下面将介紹第二種工廠模式——工廠方法模式。

定義

  在工廠方法模式中,我們不再提供一個統一的工廠類來建立所有的産品對象,而是針對不同的産品提供不同的工廠,系統提供一個與産品等級結構對應的工廠等級結構。工廠方法模式定義如下:

   工廠方法模式(Factory Method Pattern):定義一個用于建立對象的接口,讓子類決定将哪一個類執行個體化。工廠方法模式讓一個類的執行個體化延遲到其子類。工廠方法模式又簡稱為工廠模式(Factory Pattern),又可稱作虛拟構造器模式(Virtual Constructor Pattern)或多态工廠模式(Polymorphic Factory Pattern)。工廠方法模式是一種類建立型模式。

   Factory Method Pattern:Define an interface for creating an object,but let subclass decide which class to instantiate.Factory Method lets a class defer instantiation to subclass.

結構

  工廠方法模式提供一個抽象工廠接口來聲明抽象工廠方法,而由其子類來具體實作工廠方法,建立具體的産品對象。工廠方法模式結構如圖所示:

設計模式(19):建立型-簡單工廠模式(Simple Factory)及工廠方法模式(Factory Method)一.簡單工廠模式(Simple Factory)二.工廠方法模式(Factory Method)三.日志記錄器的設計四.重載的工廠方法五.工廠方法的隐藏六.工廠方法模式總結

在工廠方法模式結構圖中包含如下幾個角色:

  • Product(抽象産品):它是定義産品的接口,是工廠方法模式所建立對象的超類型,也就是産品對象的公共父類。
  • ConcreteProduct(具體産品):它實作了抽象産品接口,某種類型的具體産品由專門的具體工廠建立,具體工廠和具體産品之間一一對應。
  • Factory(抽象工廠):在抽象工廠類中,聲明了工廠方法(Factory Method),用于傳回一個産品。抽象工廠是工廠方法模式的核心,所有建立對象的工廠類都必須實作該接口。
  • ConcreteFactory(具體工廠):它是抽象工廠類的子類,實作了抽象工廠中定義的工廠方法,并可由用戶端調用,傳回一個具體産品類的執行個體。

實作

  與簡單工廠模式相比,工廠方法模式最重要的差別是引入了抽象工廠角色,抽象工廠可以是接口,也可以是抽象類或者具體類,其典型代碼如下所示:

  

public interface Factory {    
    public Product factoryMethod();    
}    
           

在抽象工廠中聲明了工廠方法但并未實作工廠方法,具體産品對象的建立由其子類負責,用戶端針對抽象工廠程式設計,可在運作時再指定具體工廠類,具體工廠類實作了工廠方法,不同的具體工廠可以建立不同的具體産品,其典型代碼如下所示:

public class ConcreteFactory implements Factory {    
    public Product factoryMethod() {    
        return new ConcreteProduct();    
    }    
}   
           

在實際使用時,具體工廠類在實作工廠方法時除了建立具體産品對象之外,還可以負責産品對象的初始化工作以及一些資源和環境配置工作,例如連接配接資料庫、建立檔案等。

在用戶端代碼中,隻需關心工廠類即可,不同的具體工廠可以建立不同的産品,典型的用戶端類代碼片段如下所示:

……    
Factory factory;    
factory = new ConcreteFactory(); //可通過配置檔案實作    
Product product;    
product = factory.factoryMethod();    
……    
           

三.日志記錄器的設計

  Sunny軟體公司欲開發一個系統運作日志記錄器(Logger),該記錄器可以通過多種途徑儲存系統的運作日志,如通過檔案記錄或資料庫記錄,使用者可以通過修改配置檔案靈活地更換日志記錄方式。在設計各類日志記錄器時,Sunny公司的開發人員發現需要對日志記錄器進行一些初始化工作,初始化參數的設定過程較為複雜,而且某些參數的設定有嚴格的先後次序,否則可能會發生記錄失敗。如何封裝記錄器的初始化過程并保證多種記錄器切換的靈活性是Sunny公司開發人員面臨的一個難題。

  Sunny公司開發人員決定使用工廠方法模式來設計日志記錄器,其基本結構如圖所示:

設計模式(19):建立型-簡單工廠模式(Simple Factory)及工廠方法模式(Factory Method)一.簡單工廠模式(Simple Factory)二.工廠方法模式(Factory Method)三.日志記錄器的設計四.重載的工廠方法五.工廠方法的隐藏六.工廠方法模式總結

在圖中,Logger接口充當抽象産品,其子類FileLogger和DatabaseLogger充當具體産品,LoggerFactory接口充當抽象工廠,其子類FileLoggerFactory和DatabaseLoggerFactory充當具體工廠。完整代碼如下所示:

//日志記錄器接口:抽象産品    
public interface Logger {    
    public void writeLog();    
}    

//資料庫日志記錄器:具體産品    
class DatabaseLogger implements Logger {    
    public void writeLog() {    
        System.out.println("資料庫日志記錄。");    
    }    
}    

//檔案日志記錄器:具體産品    
class FileLogger implements Logger {    
    public void writeLog() {    
        System.out.println("檔案日志記錄。");    
    }    
}    

//日志記錄器工廠接口:抽象工廠    
public interface LoggerFactory {    
    public Logger createLogger();    
}    

//資料庫日志記錄器工廠類:具體工廠    
class DatabaseLoggerFactory implements LoggerFactory {    
    public Logger createLogger() {    
            //連接配接資料庫,代碼省略    
            //建立資料庫日志記錄器對象    
            Logger logger = new DatabaseLogger();     
            //初始化資料庫日志記錄器,代碼省略    
            return logger;    
    }       
}    

//檔案日志記錄器工廠類:具體工廠    
class FileLoggerFactory implements LoggerFactory {    
    public Logger createLogger() {    
            //建立檔案日志記錄器對象    
            Logger logger = new FileLogger();     
            //建立檔案,代碼省略    
            return logger;    
    }       
}   
           

用戶端測試代碼:

public class Client {    
    public static void main(String args[]) {  
        LoggerFactory factory = new FileLoggerFactory(); //可引入配置檔案實作    
        Logger logger = factory.createLogger();    
        logger.writeLog();    
    }    
}  
           

輸出結果如下:

檔案日志記錄。
           

 

  為了讓系統具有更好的靈活性和可擴充性,Sunny公司開發人員決定對日志記錄器用戶端代碼進行重構,使得可以在不修改任何用戶端代碼的基礎上更換或增加新的日志記錄方式。

  在用戶端代碼中将不再使用new關鍵字來建立工廠對象,而是将具體工廠類的類名存儲在配置檔案(如XML檔案)中,通過讀取配置檔案擷取類名字元串,再使用Java的反射機制,根據類名字元串生成對象。在整個實作過程中需要用到兩個技術:Java反射機制與配置檔案讀取。軟體系統的配置檔案通常為XML檔案,我們可以使用DOM (Document Object Model)、SAX (Simple API for XML)、StAX (Streaming API for XML)等技術來處理XML檔案。關于DOM、SAX、StAX等技術的詳細學習大家可以參考其他相關資料,在此不予擴充。  

四.重載的工廠方法

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

設計模式(19):建立型-簡單工廠模式(Simple Factory)及工廠方法模式(Factory Method)一.簡單工廠模式(Simple Factory)二.工廠方法模式(Factory Method)三.日志記錄器的設計四.重載的工廠方法五.工廠方法的隐藏六.工廠方法模式總結

  引入重載方法後,抽象工廠LoggerFactory的代碼修改如下:

interface LoggerFactory {    
    public Logger createLogger();    
    public Logger createLogger(String args);    
    public Logger createLogger(Object obj);    
}   
           

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

class DatabaseLoggerFactory implements LoggerFactory {    
    public Logger createLogger() {    
            //使用預設方式連接配接資料庫,代碼省略    
            Logger logger = new DatabaseLogger();     
            //初始化資料庫日志記錄器,代碼省略    
            return logger;    
    }    

    public Logger createLogger(String args) {    
            //使用參數args作為連接配接字元串來連接配接資料庫,代碼省略    
            Logger logger = new DatabaseLogger();     
            //初始化資料庫日志記錄器,代碼省略    
            return logger;    
    }       

    public Logger createLogger(Object obj) {    
            //使用封裝在參數obj中的連接配接字元串來連接配接資料庫,代碼省略    
            Logger logger = new DatabaseLogger();     
            //使用封裝在參數obj中的資料來初始化資料庫日志記錄器,代碼省略    
            return logger;    
    }       
}    

//其他具體工廠類代碼省略   
           

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

五.工廠方法的隐藏

  有時候,為了進一步簡化用戶端的使用,還可以對用戶端隐藏工廠方法,此時,在工廠類中将直接調用産品類的業務方法,用戶端無須調用工廠方法建立産品,直接通過工廠即可使用所建立的對象中的業務方法。

  如果對用戶端隐藏工廠方法,日志記錄器的結構圖将修改為圖所示:

  

設計模式(19):建立型-簡單工廠模式(Simple Factory)及工廠方法模式(Factory Method)一.簡單工廠模式(Simple Factory)二.工廠方法模式(Factory Method)三.日志記錄器的設計四.重載的工廠方法五.工廠方法的隐藏六.工廠方法模式總結

  抽象工廠類LoggerFactory的代碼修改如下:

  

//改為抽象類    
abstract class LoggerFactory {    
    //在工廠類中直接調用日志記錄器類的業務方法writeLog()    
    public void writeLog() {    
        Logger logger = this.createLogger();    
        logger.writeLog();    
    }    

    public abstract Logger createLogger();      
}    
           

用戶端代碼修改如下:

class Client {    
    public static void main(String args[]) {    
        LoggerFactory factory;    
        factory = (LoggerFactory)XMLUtil.getBean();    
        factory.writeLog(); //直接使用工廠對象來調用産品對象的業務方法    
    }    
}    
           

  通過将業務方法的調用移入工廠類,可以直接使用工廠對象來調用産品對象的業務方法,用戶端無須直接使用工廠方法,在某些情況下我們也可以使用這種設計方案。

六.工廠方法模式總結

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

1. 主要優點

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

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

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

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

2. 主要缺點

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

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

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

3. 适用場景

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

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

(2) 抽象工廠類通過其子類來指定建立哪個對象。在工廠方法模式中,對于抽象工廠類隻需要提供一個建立産品的接口,而由其子類來确定具體要建立的對象,利用面向對象的多态性和裡氏代換原則,在程式運作時,子類對象将覆寫父類對象,進而使得系統更容易擴充。

練習

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

以上内容來自于博文:

JAVA設計模式(24):建立型-工廠模式【工廠方法模式】(Factory Method)

JAVA設計模式(01):建立型-工廠模式【簡單工廠模式】(Simple Factory)

【作者:劉偉(Sunny) http://blog.csdn.net/lovelion】

參考電子書下載下傳:設計模式的藝術–軟體開發人員内功修煉之道_劉偉(2013年).pdf

《道德經》第二十二章:

曲則全,枉則直,窪則盈,敝則新,少則得,多則惑。是以聖人抱一為天下式。不自見,故明;不自是,故彰,不自伐,故有功;不自矜,故長。夫唯不争,故天下莫能與之争。古之所謂”曲則全”者,豈虛言哉?誠全而歸之。

譯文:委曲便會保全,屈枉便會直伸;低窪便會充盈,陳舊便會更新;少取便會獲得,貪多便會迷惑。是以有道的人堅守這一原則作為天下事理的範式,不自我表揚,反能顯明;不自以為是,反能是非彰明;不自己誇耀,反能得有功勞;不自我矜持,是以才能長久。正因為不與人争,是以遍天下沒有人能與他争。古時所謂“委曲便會保全”的話,怎麼會是空話呢?它實實在在能夠達到。

繼續閱讀