一起學模式之抽象工廠

聞人_發表於2018-09-21

前言

學習過簡單工廠,工廠方法模式後,我們再來看下工廠模式中最後一個模式:抽象工廠模式。它是《設計模式》之一,並且被廣泛應用在程式框架中。本文主要從以下方面進行:

  • 模式定義
  • 編碼實踐
  • 優劣分析
  • 場景應用

正文

模式定義

首先我們來看下抽象工廠的定義:

維基百科

The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes

意思就是為建立一組有公共目標且獨立的工廠提供介面, 而無需指定它們的具體類, 而具體工廠只負責生成對應的產品.

抽象工廠定義比較抽象,那該如何理解呢,這裡我舉個例子, 我們常用的計算機分為伺服器和PC,具有共同的特性,比如CPU,記憶體,磁碟容量等等, 他們有著不同應用的場景和需求; 因此他們的製造細節和效能都是有所差別的,於是每個產品都由專門工廠來生成,伺服器由伺服器工廠來製造,PC由PC工廠來製造.由於製造流程是一致的,我們就把伺服器工廠和PC工廠的製造流程統一抽象出來,作為一個規範,具體實現由這些工廠根據自己的產品去實現. 這樣建立模式就是抽象工廠模式,不知你明白一點了沒有,這裡我用類圖表示下來幫助理解.

image-20180919074946827

下圖為抽象模式的通用類圖, 抽象工廠模式目的就是提供一個建立多個工廠類的工廠抽象類或者介面,而無需指定它們的具體類,去生成一組屬於一個產品家族的產品. 這裡產品家族就表示一類具有相互依賴,或者公共屬性的產品線.比如上文例子中伺服器工廠及產品,PC工廠及產品就是一個產品家族.

image-20180918081839854

編碼實踐

現在我們就用程式碼實現上文的例子

/**
 * @author One
 * @description 抽象工廠模式實戰
 * @date 2018/09/19
 */
public class AbastractFactoryLab {
    public static void main(String[] args) {
        ComputerFactory computerFactory = new ServerComputerFactory("2.9GHz", "16GB");
        Computer computer = computerFactory.createComputer();
        System.out.println(computer.getClass().getSimpleName() + " config :" + computer);
        //ServerComputer config :cpu: 2.9GHz, memory: 16GB
        computerFactory = new PCComputerFactory("2.4GHz", "4GB");
        computer = computerFactory.createComputer();
        System.out.println(computer.getClass().getSimpleName() + " config :" + computer);
        //PCComputer config :cpu: 2.4GHz, memory: 4GB
    }
}

/**
 * 計算機工廠介面,亦可以是抽象類
 */
interface ComputerFactory {
    Computer createComputer();
}

/**
 * 伺服器產品工廠類
 */
class ServerComputerFactory implements ComputerFactory {
    private String cpu;
    private String memory;

    ServerComputerFactory(String cpu, String memory) {
        this.cpu = cpu;
        this.memory = memory;
    }

    @Override
    public Computer createComputer() {
        return new ServerComputer(this.cpu, this.memory);
    }
}

/**
 * PC產品工廠類
 */
class PCComputerFactory implements ComputerFactory {
    private String cpu;
    private String memory;

    PCComputerFactory(String cpu, String memory) {
        this.cpu = cpu;
        this.memory = memory;
    }

    @Override
    public Computer createComputer() {
        return new PCComputer(this.cpu, this.memory);
    }
}


/**
 * 抽象產品類
 */
abstract class Computer {
    abstract String getCPU();

    abstract String getMemory();

    @Override
    public String toString() {
        return "cpu: " + getCPU() + ", memory: " + getMemory();
    }
}

/**
 * 伺服器產品
 */
class ServerComputer extends Computer {
    private String cpu;
    private String memory;

    ServerComputer(String cpu, String memory) {
        this.cpu = cpu;
        this.memory = memory;
    }

    @Override
    String getCPU() {
        return this.cpu;
    }

    @Override
    String getMemory() {
        return this.memory;
    }
}

/**
 * PC產品
 */
class PCComputer extends Computer {
    private String cpu;
    private String memory;

    PCComputer(String cpu, String memory) {
        this.cpu = cpu;
        this.memory = memory;
    }

    @Override
    String getCPU() {
        return this.cpu;
    }

    @Override
    String getMemory() {
        return this.memory;
    }
}
複製程式碼

優劣分析

優勢

  • 保證了封裝性,使用介面和抽象,只要知道工廠類即可建立對應需要產品物件。
  • 內部實現產品族內的約束,對外部透明。
  • 面向介面開發,而不是實現,更加動態化。

缺點

橫向擴充套件容易,縱向擴充套件困難;新增一個產品族,只要提供對應工廠就可以,但是產品族擴充套件困難,要新增一個新產品,就要在抽象類新增對應的生產方法,從而影響所有實現類。

場景應用

使用抽象工廠模式我們可以應對以下場景:

  • 執行時決定呼叫哪個產品類。
  • 構造具有很多依賴的複雜物件。
  • 物件構造邏輯易變且根據配置決定。

我們也可以參照抽象工廠模式在優秀原始碼裡的使用:

  • javax.xml.parsers.DocumentBuilderFactory#newInstance()

  • javax.xml.transform.TransformerFactory#newInstance()

  • javax.xml.xpath.XPathFactory#newInstance()

  • org.springframework.beans.factory.FactoryBean#getObject()

結語

本文進一步學習了抽象工廠模式,從定義和案例原始碼出發去理解,掌握模式的優缺點和應用場景。 最後再考慮個問題:工廠方法和抽象工廠的差異是什麼呢?在我看來,工廠方法模式解決的是一個工廠生產多個同類產品的問題,而抽象工廠讓每個產品有對應工廠來生產,無須關心具體的產品類,就能從對應工廠處獲得產品類。

參考

相關文章