參考:https://www.cnblogs.com/WindSun/p/10253248.html
模式動機
在工廠方法模式中具體工廠負責(zé)生產(chǎn)具體的產(chǎn)品卜高,每一個具體工廠對應(yīng)一種具體產(chǎn)品,工廠方法也具有唯一性南片,一般情況下掺涛,一個具體工廠中只有一個工廠方法或者一組重載的工廠方法。但是有時候我們需要一個工廠可以提供多個產(chǎn)品對象疼进,而不是單一的產(chǎn)品對象薪缆。
為了更清晰地理解工廠方法模式,需要先引入兩個概念:
? 產(chǎn)品等級結(jié)構(gòu):產(chǎn)品等級結(jié)構(gòu)即產(chǎn)品的繼承結(jié)構(gòu)伞广,如一個抽象類是電視機拣帽,其子類有海爾電視機、海信電視機嚼锄、TCL電視機减拭,則抽象電視機與具體品牌的電視機之間構(gòu)成了一個產(chǎn)品等級結(jié)構(gòu),抽象電視機是父類灾票,而具體品牌的電視機是其子類峡谊。
? 產(chǎn)品族:在抽象工廠模式中,產(chǎn)品族是指由同一個工廠生產(chǎn)的刊苍,位于不同產(chǎn)品等級結(jié)構(gòu)中的一組產(chǎn)品,如海爾電器工廠生產(chǎn)的海爾電視機濒析、海爾電冰箱正什,海爾電視機位于電視機產(chǎn)品等級結(jié)構(gòu)中,海爾電冰箱位于電冰箱產(chǎn)品等級結(jié)構(gòu)中号杏。
產(chǎn)品族與產(chǎn)品等級結(jié)構(gòu)示意圖:
當(dāng)系統(tǒng)所提供的工廠所需生產(chǎn)的具體產(chǎn)品并不是一個簡單的對象婴氮,而是多個位于不同產(chǎn)品等級結(jié)構(gòu)中屬于不同類型的具體產(chǎn)品時需要使用抽象工廠模式。
抽象工廠模式是所有形式的工廠模式中最為抽象和最具一般性的一種形態(tài)盾致。
抽象工廠模式與工廠方法模式最大的區(qū)別在于主经,工廠方法模式針對的是一個產(chǎn)品等級結(jié)構(gòu),而抽象工廠模式則需要面對多個產(chǎn)品等級結(jié)構(gòu)庭惜,一個工廠等級結(jié)構(gòu)可以負責(zé)多個不同產(chǎn)品等級結(jié)構(gòu)中的產(chǎn)品對象的創(chuàng)建 罩驻。當(dāng)一個工廠等級結(jié)構(gòu)可以創(chuàng)建出分屬于不同產(chǎn)品等級結(jié)構(gòu)的一個產(chǎn)品族中的所有對象時,抽象工廠模式比工廠方法模式更為簡單护赊、有效率惠遏。
模式定義
抽象工廠模式(Abstract Factory Pattern):提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口砾跃,而無須指定它們具體的類。抽象工廠模式又稱為Kit模式节吮,屬于對象創(chuàng)建型模式抽高。
模式結(jié)構(gòu)
抽象工廠模式包含如下角色:
? AbstractFactory:抽象工廠
? ConcreteFactory:具體工廠
? AbstractProduct:抽象產(chǎn)品
? Product:具體產(chǎn)品
模式分析
抽象工廠類的典型代碼如下:
public abstract class AbstractFactory{
public abstract AbstractProductA createProductA();
public abstract AbstractProductB createProductB();
}
具體工廠類的典型代碼如下:
public class ConcreteFactory1 extends AbstractFactory
{
public AbstractProductA createProductA()
{
return new ConcreteProductA1();
}
public AbstractProductB createProductB()
{
return new ConcreteProductB1();
}
}
模式實例與解析
實例一:電器工廠
-
一個電器工廠可以產(chǎn)生多種類型的電器,如海爾工廠可以生產(chǎn)海爾電視機透绩、海爾空調(diào)等翘骂,TCL工廠可以生產(chǎn)TCL電視機、TCL空調(diào)等帚豪,相同品牌的電器構(gòu)成一個產(chǎn)品族雏胃,而相同類型的電器構(gòu)成了一個產(chǎn)品等級結(jié)構(gòu),現(xiàn)使用抽象工廠模式模擬該場景志鞍。
實例代碼(JAVA):
//抽象產(chǎn)品 Television
public interface Television
{
public void play();
}
//具體產(chǎn)品 HaierTelevision
public class HaierTelevision implements Television
{
public void play()
{
System.out.println("海爾電視機播放中......");
}
}
//具體產(chǎn)品 TCLTelevision
public class TCLTelevision implements Television
{
public void play()
{
System.out.println("TCL電視機播放中......");
}
}
//抽象產(chǎn)品 AirConditioner
public interface AirConditioner
{
public void changeTemperature();
}
//具體產(chǎn)品 HaierAirConditioner
public class HaierAirConditioner implements AirConditioner
{
public void changeTemperature()
{
System.out.println("海爾空調(diào)溫度改變中......");
}
}
//具體產(chǎn)品 TCLAirConditioner
public class TCLAirConditioner implements AirConditioner
{
public void changeTemperature()
{
System.out.println("TCL空調(diào)溫度改變中......");
}
}
//抽象工廠 EFactory
public interface EFactory
{
public Television produceTelevision();
public AirConditioner produceAirConditioner();
}
//具體工廠 HaierFactory
public class HaierFactory implements EFactory
{
public Television produceTelevision()
{
return new HaierTelevision();
}
public AirConditioner produceAirConditioner()
{
return new HaierAirConditioner();
}
}
//具體工廠 TCLFactory
public class TCLFactory implements EFactory
{
public Television produceTelevision()
{
return new TCLTelevision();
}
public AirConditioner produceAirConditioner()
{
return new TCLAirConditioner();
}
}
運行結(jié)果:
實例二:數(shù)據(jù)庫操作工廠
? 某系統(tǒng)為了改進數(shù)據(jù)庫操作的性能瞭亮,自定義數(shù)據(jù)庫連接對象Connection和語句對象Statement,可針對不同類型的數(shù)據(jù)庫提供不同的連接對象和語句對象固棚,如提供Oracle或SQL Server專用連接類和語句類统翩,而且用戶可以通過配置文件等方式根據(jù)實際需要動態(tài)更換系統(tǒng)數(shù)據(jù)庫。使用抽象工廠模式設(shè)計該系統(tǒng)此洲。
模式優(yōu)缺點
優(yōu)點
? 抽象工廠模式隔離了具體類的生成厂汗,使得客戶并不需要知道什么被創(chuàng)建。由于這種隔離呜师,更換一個具體工廠就變得相對容易娶桦。所有的具體工廠都實現(xiàn)了抽象工廠中定義的那些公共接口,因此只需改變具體工廠的實例汁汗,就可以在某種程度上改變整個軟件系統(tǒng)的行為衷畦。另外,應(yīng)用抽象工廠模式可以實現(xiàn)高內(nèi)聚低耦合的設(shè)計目的知牌,因此抽象工廠模式得到了廣泛的應(yīng)用祈争。
? 當(dāng)一個產(chǎn)品族中的多個對象被設(shè)計成一起工作時,它能夠保證客戶端始終只使用同一個產(chǎn)品族中的對象角寸。這對一些需要根據(jù)當(dāng)前環(huán)境來決定其行為的軟件系統(tǒng)來說菩混,是一種非常實用的設(shè)計模式。
? 增加新的具體工廠和產(chǎn)品族很方便扁藕,無須修改已有系統(tǒng)沮峡,符合“開閉原則”。
缺點
? 在添加新的產(chǎn)品對象時亿柑,難以擴展抽象工廠來生產(chǎn)新種類的產(chǎn)品邢疙,這是因為在抽象工廠角色中規(guī)定了所有可能被創(chuàng)建的產(chǎn)品集合,要支持新種類的產(chǎn)品就意味著要對該接口進行擴展,而這將涉及到對抽象工廠角色及其所有子類的修改秘症,顯然會帶來較大的不便照卦。
? 開閉原則的傾斜性(增加新的工廠和產(chǎn)品族容易,增加新的產(chǎn)品等級結(jié)構(gòu)麻煩)
模式適用環(huán)境
在以下情況下可以使用抽象工廠模式:
? 一個系統(tǒng)不應(yīng)當(dāng)依賴于產(chǎn)品類實例如何被創(chuàng)建乡摹、組合和表達的細節(jié)役耕,這對于所有類型的工廠模式都是重要的。
? 系統(tǒng)中有多于一個的產(chǎn)品族聪廉,而每次只使用其中某一產(chǎn)品族瞬痘。
? 屬于同一個產(chǎn)品族的產(chǎn)品將在一起使用,這一約束必須在系統(tǒng)的設(shè)計中體現(xiàn)出來板熊。
? 系統(tǒng)提供一個產(chǎn)品類的庫框全,所有的產(chǎn)品以同樣的接口出現(xiàn),從而使客戶端不依賴于具體實現(xiàn)干签。
模式應(yīng)用
(1) Java SE AWT(抽象窗口工具包)
Java語言的AWT(抽象窗口工具包)中就使用了抽象工廠模式津辩,它使用抽象工廠模式來實現(xiàn)在不同的操作系統(tǒng)中應(yīng)用程序呈現(xiàn)與所在操作系統(tǒng)一致的外觀界面。
(2) 在很多軟件系統(tǒng)中需要更換界面主題容劳,要求界面中的按鈕喘沿、文本框、背景色等一起發(fā)生改變時竭贩,可以使用抽象工廠模式進行設(shè)計蚜印。
模式擴展
“開閉原則”的傾斜性
“開閉原則”要求系統(tǒng)對擴展開放,對修改封閉留量,通過擴展達到增強其功能的目的窄赋。對于涉及到多個產(chǎn)品族與多個產(chǎn)品等級結(jié)構(gòu)的系統(tǒng),其功能增強包括兩方面:
(1) 增加產(chǎn)品族:對于增加新的產(chǎn)品族楼熄,工廠方法模式很好的支持了“開閉原則”忆绰,對于新增加的產(chǎn)品族,只需要對應(yīng)增加一個新的具體工廠即可孝赫,對已有代碼無須做任何修改较木。
(2) 增加新的產(chǎn)品等級結(jié)構(gòu):對于增加新的產(chǎn)品等級結(jié)構(gòu),需要修改所有的工廠角色青柄,包括抽象工廠類,在所有的工廠類中都需要增加生產(chǎn)新產(chǎn)品的方法预侯,不能很好地支持“開閉原則”致开。
抽象工廠模式的這種性質(zhì)稱為“開閉原則”的傾斜性,抽象工廠模式以一種傾斜的方式支持增加新的產(chǎn)品萎馅,它為新產(chǎn)品族的增加提供方便双戳,但不能為新的產(chǎn)品等級結(jié)構(gòu)的增加提供這樣的方便。
工廠模式的退化
當(dāng)抽象工廠模式中每一個具體工廠類只創(chuàng)建一個產(chǎn)品對象糜芳,也就是只存在一個產(chǎn)品等級結(jié)構(gòu)時飒货,抽象工廠模式退化成工廠方法模式魄衅;當(dāng)工廠方法模式中抽象工廠與具體工廠合并,提供一個統(tǒng)一的工廠來創(chuàng)建產(chǎn)品對象塘辅,并將創(chuàng)建對象的工廠方法設(shè)計為靜態(tài)方法時晃虫,工廠方法模式退化成簡單工廠模式。