抽象工廠模式(Abstract factory pattern)
抽象工廠模式(Abstract factory pattern)是一種軟件開發(fā)設(shè)計(jì)模式粟耻。抽象工廠模式提供了一種方式,可以將一組具有同一主題的單獨(dú)的工廠封裝起來。在正常使用中,客戶端程序需要?jiǎng)?chuàng)建抽象工廠的具體實(shí)現(xiàn)跨释,然后使用抽象工廠作為接口來創(chuàng)建這一主題的具體對(duì)象官地〉薅恚客戶端程序不需要知道(或關(guān)心)它從這些內(nèi)部的工廠方法中獲得對(duì)象的具體類型疗绣,因?yàn)榭蛻舳顺绦騼H使用這些對(duì)象的通用接口线召。抽象工廠模式將一組對(duì)象的實(shí)現(xiàn)細(xì)節(jié)與他們的一般使用分離開來。
定義:為創(chuàng)建一組相關(guān)或相互依賴的對(duì)象提供一個(gè)接口多矮,而且無需指定他們的具體類缓淹。
類型:創(chuàng)建類模式
類圖:
GuiFactory
接口中的createButton
方法返回Button
類型的對(duì)象。返回Button
的哪種實(shí)現(xiàn)依賴于使用GuiFactory
的哪種實(shí)現(xiàn)工窍。
需要注意的是割卖,為了簡(jiǎn)潔起見,以上類圖僅僅展示了創(chuàng)建一個(gè)類型對(duì)象的工廠患雏。而在抽象工廠模式中鹏溯,通常一個(gè)工廠能夠創(chuàng)建若干種不同類型的對(duì)象。
產(chǎn)品族
先來認(rèn)識(shí)下什么是產(chǎn)品族:位于不同產(chǎn)品等級(jí)結(jié)構(gòu)中淹仑,功能相關(guān)聯(lián)的產(chǎn)品組成的家族丙挽。還是讓我們換一個(gè)例子來形象地說明一下吧。
圖中的BmwCar
和BenzCar
就是兩個(gè)產(chǎn)品樹(產(chǎn)品層次結(jié)構(gòu))匀借;而如圖所示的BenzSportsCar
和BmwSportsCar
就是一個(gè)產(chǎn)品族颜阐。他們都可以放到跑車家族中,因此功能有所關(guān)聯(lián)吓肋。同理BmwBussinessCar
和BenzSportsCar
也是一個(gè)產(chǎn)品族凳怨。
回到抽象工廠模式的話題上。
可以說是鬼,抽象工廠模式和工廠方法模式的區(qū)別就在于需要?jiǎng)?chuàng)建對(duì)象的復(fù)雜程度上肤舞。而且抽象工廠模式是三個(gè)里面最為抽象、最具一般性的均蜜。
抽象工廠模式的用意為:給客戶端提供一個(gè)接口李剖,可以創(chuàng)建多個(gè)產(chǎn)品族中的產(chǎn)品對(duì)象。
而且使用抽象工廠模式還要滿足一下條件:
- 系統(tǒng)中有多個(gè)產(chǎn)品族囤耳,而系統(tǒng)一次只可能消費(fèi)其中一族產(chǎn)品篙顺。
- 同屬于同一個(gè)產(chǎn)品族的產(chǎn)品以其使用。
來看看抽象工廠模式的各個(gè)角色(和工廠方法的如出一轍):
- 抽象工廠角色: 這是工廠方法模式的核心充择,它與應(yīng)用程序無關(guān)德玫。是具體工廠角色必須實(shí)現(xiàn)的接口或者必須繼承的父類。在java中它由抽象類或者接口來實(shí)現(xiàn)聪铺。
- 具體工廠角色:它含有和具體業(yè)務(wù)邏輯有關(guān)的代碼化焕。由應(yīng)用程序調(diào)用以創(chuàng)建對(duì)應(yīng)的具體產(chǎn)品的對(duì)象。在java中它由具體的類來實(shí)現(xiàn)铃剔。
- 抽象產(chǎn)品角色:它是具體產(chǎn)品繼承的父類或者是實(shí)現(xiàn)的接口撒桨。在java中一般有抽象類或者接口來實(shí)現(xiàn)。
- 具體產(chǎn)品角色:具體工廠角色所創(chuàng)建的對(duì)象就是此角色的實(shí)例键兜。在java中由具體的類來實(shí)現(xiàn)凤类。
類圖如下:
代碼舉例
// 產(chǎn)品 Plant接口
public interface Plant { }//標(biāo)志接口
//具體產(chǎn)品PlantA,PlantB
public class PlantA implements Plant {
public PlantA () {
System.out.println("create PlantA !");
}
public void doSomething() {
System.out.println(" PlantA do something ...");
}
}
public class PlantB implements Plant {
public PlantB () {
System.out.println("create PlantB !");
}
public void doSomething() {
System.out.println(" PlantB do something ...");
}
}
//產(chǎn)品Fruit接口
public interface Fruit { }
//具體產(chǎn)品FruitA普气,F(xiàn)ruitB
public class FruitA implements Fruit {
public FruitA() {
System.out.println("create FruitA !");
}
public void doSomething() {
System.out.println(" FruitA do something ...");
}
}
public class FruitB implements Fruit {
public FruitB() {
System.out.println("create FruitB !");
}
public void doSomething() {
System.out.println(" FruitB do something ...");
}
}
//抽象工廠方法
public interface AbstractFactory {
public Plant createPlant();
public Fruit createFruit();
}
//具體工廠方法
public class FactoryA implements AbstractFactory {
public Plant createPlant() {
return new PlantA();
}
public Fruit createFruit() {
return new FruitA();
}
}
public class FactoryB implements AbstractFactory {
public Plant createPlant() {
return new PlantB();
}
public Fruit createFruit() {
return new FruitB();
}
}
//調(diào)用工廠方法
public class Client {
public void method1() {
AbstractFactory instance = new FactoryA();
instance.createPlant();
}
}
建議可以看看GoF的《設(shè)計(jì)模式》一書谜疤,里面說到工廠模式時(shí)舉得例子淺顯易懂。
工廠方法模式與抽象工廠模式的區(qū)別
可以這么說现诀,工廠方法模式是一種極端情況的抽象工廠模式夷磕,而抽象工廠模式可以看成是工廠方法模式的一種推廣。
其實(shí)工廠方法模式是用來創(chuàng)建一個(gè)產(chǎn)品的等級(jí)結(jié)構(gòu)的仔沿,而抽象工廠模式是用來創(chuàng)建多個(gè)產(chǎn)品的等級(jí)結(jié)構(gòu)的坐桩。工廠方法創(chuàng)建一般只有一個(gè)方法,創(chuàng)建一種產(chǎn)品封锉。抽象工廠一般有多個(gè)方法绵跷,創(chuàng)建一系列產(chǎn)品。
工廠方法模式只有一個(gè)抽象產(chǎn)品類成福,而抽象工廠模式有多個(gè)碾局。工廠方法模式的具體工廠類只能創(chuàng)建一個(gè)具體產(chǎn)品類的實(shí)例,而抽象工廠模式可以創(chuàng)建多個(gè)奴艾。
簡(jiǎn)而言之净当,
工廠方法模式:
- 一個(gè)抽象產(chǎn)品類,可以派生出多個(gè)具體產(chǎn)品類蕴潦。
- 一個(gè)抽象工廠類像啼,可以派生出多個(gè)具體工廠類。
- 每個(gè)具體工廠類只能創(chuàng)建一個(gè)具體產(chǎn)品類的實(shí)例品擎。
抽象工廠模式:
- 多個(gè)抽象產(chǎn)品類埋合,每個(gè)抽象產(chǎn)品類可以派生出多個(gè)具體產(chǎn)品類。
- 一個(gè)抽象工廠類萄传,可以派生出多個(gè)具體工廠類甚颂。
- 每個(gè)具體工廠類可以創(chuàng)建多個(gè)具體產(chǎn)品類的實(shí)例。
適用性
在以下情況可以考慮使用抽象工廠模式:
- 一個(gè)系統(tǒng)要獨(dú)立于它的產(chǎn)品的創(chuàng)建秀菱、組合和表示時(shí)振诬。
- 一個(gè)系統(tǒng)要由多個(gè)產(chǎn)品系列中的一個(gè)來配置時(shí)。
- 需要強(qiáng)調(diào)一系列相關(guān)的產(chǎn)品對(duì)象的設(shè)計(jì)以便進(jìn)行聯(lián)合使用時(shí)衍菱。
- 提供一個(gè)產(chǎn)品類庫赶么,而只想顯示它們的接口而不是實(shí)現(xiàn)時(shí)。
優(yōu)點(diǎn)
- 具體產(chǎn)品從客戶代碼中被分離出來脊串。
- 容易改變產(chǎn)品的系列辫呻。
- 將一個(gè)系列的產(chǎn)品族統(tǒng)一到一起創(chuàng)建清钥。
缺點(diǎn)
- 在產(chǎn)品族中擴(kuò)展新的產(chǎn)品是很困難的,它需要修改抽象工廠的接口
參考資料: