設計模式(十三)抽象工廠模式

劉望舒發表於2017-05-23

相關文章
設計模式系列

前言

此前講解過簡單工廠模式和工廠模式,這一篇我們來學習工廠系列的最後一個模式抽象工廠模式,建議在閱讀此文前,請先閱讀設計模式(四)簡單工廠模式設計模式(十)工廠方法模式這兩篇文章。

1.抽象工廠模式定義

抽象工廠模式可以說是是工廠方法模式的升級版,當需要建立的產品有多個產品線(產品族)時使用抽象工廠模式是比較好的選擇。那什麼是多個產品線呢?拿我們在設計模式(四)簡單工廠模式設計模式(十)工廠方法模式中學習的生產電腦的例子來舉例,我們一直都是生產聯想和惠普的電腦,但是電腦也有多個產品線:桌上型電腦、筆記本和平板等等,聯想和惠普都在生產這些不同產品線上的電腦,使用工廠方法模式已經滿足不了需求,這一篇文章我們就用抽象工廠模式來解決這一問題。

抽象工廠模式定義
為建立一組相關或者相互依賴的物件提供一個介面,而無需指定它們的具體類。

抽象工廠模式UML圖

設計模式(十三)抽象工廠模式

在抽象工廠模式中有如下角色:

  • AbstractFactory:抽象工廠,它宣告瞭用來建立不同產品的方法。
  • ConcreteFactory:具體工廠,實現抽象工廠中定義的建立產品的方法。
  • AbstractProduct:抽象產品,為每種產品宣告業務方法。比如上圖的AbstractProductA和 AbstractProductB。
  • ConcreteProduct:具體產品,定義具體工廠生產的具體產品,並實現抽象產品中定義的業務方法。

2.抽象工廠模式簡單實現

聯想和惠普生產的電腦分為了兩個產品線,一個桌上型電腦,一個是筆記本。為了解決增加產品線的問題,我們用抽象工廠模式來進行實現。

抽象產品
首先定義抽象產品類:

public abstract class DesktopComputer {
  public abstract void start();
}
public abstract class NotebookComputer {
   public abstract void start();
}複製程式碼

兩個抽象產品類分別為DesktopComputer和NotebookComputer ,用來定義兩個產品線:桌上型電腦和筆記本。它們都定義了start方法,用來啟動電腦。
具體產品
具體產品為聯想和惠普旗下的桌上型電腦和筆記本,如下所示。

public class LenovoDesktopComputer extends DesktopComputer {
    @Override
    public void start() {
        System.out.println("聯想臺式電腦啟動");
    }
}

public class HpDesktopComputer extends DesktopComputer {
    @Override
    public void start() {
        System.out.println("惠普臺式電腦啟動");
    }
}

public class LenovoNotebookComputer extends NotebookComputer {
    @Override
    public void start() {
        System.out.println("聯想膝上型電腦啟動");
    }
}
public class HpNotebookComputer extends NotebookComputer {
    @Override
    public void start() {
        System.out.println("惠普膝上型電腦啟動");
    }
}複製程式碼

抽象工廠
接著建立生產電腦的抽象工廠,如下所示,

public abstract class ComputerFactory {
    public abstract DesktopComputer createDesktopComputer();
    public abstract NotebookComputer createNotebookComputer();
}複製程式碼

定義了兩個方法,分別用來生產臺式電腦和膝上型電腦。

具體工廠
定義聯想和惠普工廠:

public class LenovoFactory extends ComputerFactory {
    @Override
    public DesktopComputer createDesktopComputer() {
        return new LenovoDesktopComputer();
    }
    @Override
    public NotebookComputer createNotebookComputer() {
        return new LenovoNotebookComputer();
    }
}

public class HpFactory extends ComputerFactory {
    @Override
    public DesktopComputer createDesktopComputer() {
        return new HpDesktopComputer();
    }

    @Override
    public NotebookComputer createNotebookComputer() {
        return new HpNotebookComputer();
    }
}複製程式碼

聯想工廠和惠普工廠用來生產桌上型電腦和筆記本這兩個不同產品線的電腦。

客戶端呼叫
最後編寫客戶端:

public class Client {
    public static void main(String[]args) {
        ComputerFactory lenocoFactory=new LenovoFactory();
        lenocoFactory.createDesktopComputer().start();
        lenocoFactory.createNotebookComputer().start();
        ComputerFactory hpFactory=new HpFactory();
        hpFactory.createDesktopComputer().start();
        hpFactory.createNotebookComputer().start();
    }
}複製程式碼

分別用LenovoFactory和HpFactory生產臺式和膝上型電腦,並呼叫start方法啟動它們。
執行結果為:
聯想臺式電腦啟動
聯想膝上型電腦啟動
惠普臺式電腦啟動
惠普膝上型電腦啟動

接下來給出這個例子的UML圖,更便於理解,如下所示。

設計模式(十三)抽象工廠模式

3.抽象工廠模式的優缺點

優點
具體類的建立例項過程與客戶端分離,客戶端通過工廠的抽象介面操縱例項,客戶端並不知道具體的實現是誰。

缺點
如果增加新的產品族則也需要修改抽象工廠和所有的具體工廠。

抽象工廠模式的使用場景

  • 一個系統不依賴於產品線例項如何被建立、組合和表達的細節。
  • 系統中有多於一個的產品線,而每次只使用其中某一產品線。
  • 一個產品線(或是一組沒有任何關係的物件)擁有相同的約束。

參考資料
《大話設計模式》
《設計模式之禪》
《Android原始碼設計模式》

相關文章