設計模式系列之工廠模式三兄弟(Factory Pattern)

說明:設計模式系列文章是讀劉偉所著《設計模式的藝術之道(軟件開發人員內功修煉之道)》一書的閱讀筆記。我的感受這本書講的不錯,有興趣推薦讀一讀。詳細內容也能夠看看此書做者的博客https://blog.csdn.net/LoveLion/article/details/17517213java

工廠模式是最經常使用的一類建立型設計模式,一般咱們所說的工廠模式是指工廠方法模式,它也是使用頻率最高的工廠模式。簡單工廠模式是工廠方法模式的「小弟」,它不屬於GoF23種設計模式,但在軟件開發中應用也較爲頻繁,一般將它做爲學習其餘工廠模式的入門。此外,工廠方法模式還有一位「大哥」——抽象工廠模式。這三種工廠模式各具特點,難度也逐個加大,在軟件開發中它們都獲得了普遍的應用,成爲面向對象軟件中經常使用的建立對象的工具。編程

簡單工廠模式

簡單工廠模式並不屬於GoF 23個經典設計模式,但一般將它做爲學習其餘工廠模式的基礎,它的設計思想很簡單。設計模式

模式定義

簡單工廠模式(Simple Factory Pattern):定義一個工廠類,它能夠根據參數的不一樣返回不一樣類的實例,被建立的實例一般都具備共同的父類。由於在簡單工廠模式中用於建立實例的方法是靜態(static)方法,所以簡單工廠模式又被稱爲靜態工廠方法(Static Factory Method)模式,它屬於類建立型模式。框架

簡單工廠模式的要點在於:當你須要什麼,只須要傳入一個正確的參數,就能夠獲取你所須要的對象,而無須知道其建立細節。ide

模式結構圖

簡單工廠模式結構圖以下所示:工具

簡單工廠模式結構圖

模式僞代碼

在使用簡單工廠模式時,首先須要對產品類進行重構,不能設計一個一應俱全的產品類,而需根據實際狀況設計一個產品層次結構,將全部產品類公共的代碼移至抽象產品類,並在抽象產品類中聲明一些抽象方法,以供不一樣的具體產品類來實現,典型的抽象產品類代碼以下所示:學習

public abstract class Product {
    // 全部產品的公共屬性

    // 全部產品類的公共業務方法
    public void methodSame() {
        //公共方法的實現
    }

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

具體產品類中實現了抽象產品類中聲明的抽象業務方法。this

public class ConcreteProduct extends Product {
    @Override
    public void methodDiff() {
        // 具體產品業務方法的實現
    }
}

簡單工廠模式的核心是工廠類,在沒有工廠類以前,客戶端通常會使用new關鍵字來直接建立產品對象,而在引入工廠類以後,客戶端能夠經過工廠類來建立產品,在簡單工廠模式中,工廠類提供了一個靜態工廠方法供客戶端使用,根據所傳入的參數不一樣能夠建立不一樣的產品對象,典型的工廠類代碼以下所示:.net

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();
    }
}

模式簡化

有時候,爲了簡化簡單工廠模式,咱們能夠將抽象產品類工廠類合併,將靜態工廠方法移至抽象產品類中,以下圖所示。

簡化的簡單工廠模式

客戶端能夠經過產品父類的靜態工廠方法,根據參數的不一樣建立不一樣類型的產品子類對象,這種作法在JDK等類庫和框架中也普遍存在。
好比:java.nio.charset.Charset

public abstract class Charset {

    /**
     * Returns a charset object for the named charset.
     */
    public static Charset forName(String charsetName) {
        java.nio.charset.Charset cs = lookup(charsetName);
        if (cs != null)
            return cs;
        throw new UnsupportedCharsetException(charsetName);
    }
}

模式小結

簡單工廠模式提供了專門的工廠類用於建立對象,將對象的建立和對象的使用分離開,它做爲一種最簡單的工廠模式在軟件開發中獲得了較爲普遍的應用。

使用場景:

  1. 工廠類負責建立的對象比較少,因爲建立的對象較少,不會形成工廠方法中的業務邏輯太過複雜。
  2. 客戶端只知道傳入工廠類的參數,對於如何建立對象並不關心。

工廠方法模式

簡單工廠模式雖然簡單,但存在一個很嚴重的問題。當系統中須要引入新產品時,因爲靜態工廠方法經過所傳入參數的不一樣來建立不一樣的產品,這一定要修改工廠類的源代碼,將違背「開閉原則」,如何實現增長新產品而不影響已有代碼?工廠方法模式應運而生。

模式定義

工廠方法模式中,咱們再也不提供一個統一的工廠類來建立全部的產品對象,而是針對不一樣的產品提供不一樣的工廠,系統提供一個與產品等級結構對應的工廠等級結構。工廠方法模式定義以下:

工廠方法模式(Factory Method Pattern):定義一個用於建立對象的接口,讓子類決定將哪個類實例化。工廠方法模式讓一個類的實例化延遲到其子類。工廠方法模式又簡稱爲工廠模式(Factory Pattern),又可稱做虛擬構造器模式(Virtual Constructor Pattern)或多態工廠模式(Polymorphic Factory Pattern)。工廠方法模式是一種類建立型模式。

模式結構圖

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

工廠方法模式結構圖

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

  • Product(抽象產品):它是定義產品的接口,是工廠方法模式所建立對象的超類型,也就是產品對象的公共父類。
  • ConcreteProduct(具體產品):它實現了抽象產品接口,某種類型的具體產品由專門的具體工廠建立,具體工廠和具體產品之間一一對應。
  • Factory(抽象工廠):在抽象工廠類中,聲明瞭工廠方法(Factory Method),用於返回一個產品。抽象工廠是工廠方法模式的核心,全部建立對象的工廠類都必須實現該接口。
  • ConcreteFactory(具體工廠):它是抽象工廠類的子類,實現了抽象工廠中定義的工廠方法,並可由客戶端調用,返回一個具體產品類的實例。

模式僞代碼

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

public interface Factory {
    Product factoryMethod();
}

在抽象工廠中聲明瞭工廠方法但並未實現工廠方法,具體產品對象的建立由其子類負責,客戶端針對抽象工廠編程,可在運行時再指定具體工廠類,具體工廠類實現了工廠方法,不一樣的具體工廠能夠建立不一樣的具體產品,其典型代碼以下所示:

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

在客戶端代碼中,只需關心工廠類便可,不一樣的具體工廠能夠建立不一樣的產品,典型的客戶端類代碼片斷以下所示:

public class Client {
    public static void main(String[] args) {
        // 肯定是哪一個工廠可獲得產品
        Factory factory = new ConcreteFactory();
        // 獲取產品
        Product product = factory.factoryMethod();
    }
}

模式簡化

有時候,爲了進一步簡化客戶端的使用,還能夠對客戶端隱藏工廠方法,此時,在工廠類中將直接調用產品類的業務方法,客戶端無須調用工廠方法建立產品,直接經過工廠便可使用所建立的對象中的業務方法。

// 改成抽象類
public class AbstractFactory {
    // 在工廠類中直接調用產品類的業務方法
    public void productMethod() {
        Product product = this.createProduct();
        product.method();
    }

    public abstract Product createProduct();
}

經過將業務方法的調用移入工廠類,能夠直接使用工廠對象來調用產品對象的業務方法,客戶端無須直接調用工廠方法,在客戶端並不關心Product細節的狀況下使用這種設計方案會更加方便。

模式小結

工廠方法模式可以讓工廠能夠自主肯定建立何種產品對象,而如何建立這個對象的細節則徹底封裝在具體工廠內部,用戶只須要關心所需產品對應的工廠,無須關心建立細節,甚至無須知道具體產品類的類名。基於工廠角色產品角色的多態性設計是工廠方法模式的關鍵。

抽象工廠模式

工廠方法模式經過引入工廠等級結構,解決了簡單工廠模式中工廠類職責過重的問題,但因爲工廠方法模式中的每一個工廠只生產一類產品,可能會致使系統中存在大量的工廠類,勢必會增長系統的開銷。此時,咱們能夠考慮將一些相關的產品組成一個產品族,由同一個工廠來統一輩子產,這就是咱們本文將要學習的抽象工廠模式的基本思想。

這裏我斗膽舉個例子來講明一下吧,若是不恰當歡迎指出。

衆所周知,國內知名的電器廠有海爾、海信(姑且就認爲是2個),電器廠會生產電視機、電冰箱、空調(姑且就認爲是3種產品)。

  • 使用工廠方法模式:工廠方法模式中每一個工廠只生產一類產品,那麼就必需要有海爾電視機廠海爾電冰箱廠海爾空調廠海信電視機廠海信電冰箱廠海信空調廠
  • 使用抽象工廠模式:抽象工廠中每一個工廠生產由多種產品組成的"產品族",那麼就只須要有海爾工廠海信工廠就夠了,每一個工廠可生產自家的電視機、電冰箱、空調。

由此看出使用抽象工廠模式極大地減小了系統中類的個數。

模式定義

抽象工廠模式爲建立一組對象提供了一種解決方案。與工廠方法模式相比,抽象工廠模式中的具體工廠不僅是建立一種產品,它負責建立一族產品。抽象工廠模式定義以下:

抽象工廠模式(Abstract Factory Pattern):提供一個建立一系列相關或相互依賴對象的接口,而無須指定它們具體的類。抽象工廠模式又稱爲Kit模式,它是一種對象建立型模式。

模式結構圖

在抽象工廠模式中,每個具體工廠都提供了多個工廠方法用於產生多種不一樣類型的產品,這些產品構成了一個產品族,抽象工廠模式結構如圖所示:

抽象工廠模式結構圖

在抽象工廠模式結構圖中包含以下幾個角色:

  • AbstractFactory(抽象工廠):它聲明瞭一組用於建立一族產品的方法,每個方法對應一種產品。
  • ConcreteFactory(具體工廠):它實現了在抽象工廠中聲明的建立產品的方法,生成一組具體產品,這些產品構成了一個產品族,每個產品都位於某個產品等級結構中。
  • AbstractProduct(抽象產品):它爲每種產品聲明接口,在抽象產品中聲明瞭產品所具備的業務方法。
  • ConcreteProduct(具體產品):它定義具體工廠生產的具體產品對象,實現抽象產品接口中聲明的業務方法。

模式僞代碼

在抽象工廠中聲明瞭多個工廠方法,用於建立不一樣類型的產品,抽象工廠能夠是接口,也能夠是抽象類或者具體類,其典型代碼以下所示:

public abstract class AbstractFactory {

    public abstract AbstractProductA createProductA();

    public abstract AbstractProductB createProductB();

    public abstract AbstractProductC createProductC();
}

具體工廠實現了抽象工廠,每個具體的工廠方法能夠返回一個特定的產品對象,而同一個具體工廠所建立的產品對象構成了一個產品族。對於每個具體工廠類,其典型代碼以下所示:

public class ConcreteFactory1 extends AbstractFactory {
    @Override
    public AbstractProductA createProductA() {
        return new ConcreteProductA1();
    }

    @Override
    public AbstractProductB createProductB() {
        return new ConcreteProductB1();
    }

    @Override
    public AbstractProductC createProductC() {
        return new ConcreteProductC1();
    }
}

模式小結

若是一開始就學習抽象工廠模式估計很難理解爲何這樣設計,按次序學習分析簡單工廠模式工廠方法模式抽象工廠模式基本就瓜熟蒂落了。實際開發中,可能並非照搬照套工廠模式三兄弟的僞代碼,大多會簡化其中的部分實現。原本學習設計模式就是重思想,學習如何用抽象類、接口、拆分、組合等將軟件解耦合,並加強系統可擴展性,這纔是最關鍵的。

相關文章
相關標籤/搜索