抽象工廠模式產(chǎn)生的動機:
? ? ? ?為了更清晰地理解工廠方法模式,需要先引入兩個概念:
? ? ?? 產(chǎn)品等級結構 :產(chǎn)品等級結構即產(chǎn)品的繼承結構,如一個抽象類是電視機,其子類有海爾電視機、海信電視機、TCL電視機,則抽象電視機與具體品牌的電視機之間構成了一個產(chǎn)品等級結構,抽象電視機是父類,而具體品牌的電視機是其子類。
?? ? ? ?產(chǎn)品族 :在抽象工廠模式中,產(chǎn)品族是指由同一個工廠生產(chǎn)的,位于不同產(chǎn)品等級結構中的一組產(chǎn)品,如海爾電器工廠生產(chǎn)的海爾電視機、海爾電冰箱,海爾電視機位于電視機產(chǎn)品等級結構中,海爾電冰箱位于電冰箱產(chǎn)品等級結構中。

在工廠方法模式中具體工廠負責生產(chǎn)具體的產(chǎn)品,每一個具體工廠對應一種具體產(chǎn)品,工廠方法也具有唯一性,一般情況下, 一個具體工廠中只有一個工廠方法或者一組重載的工廠方法。但是有時候我們需要一個工廠可以提供多個產(chǎn)品對象,而不是單一的產(chǎn)品對象。??
當系統(tǒng)所提供的工廠所需生產(chǎn)的具體產(chǎn)品并不是一個簡單的對象,而是多個位于不同產(chǎn)品等級結構中屬于不同類型的具體產(chǎn)品時需要使用抽象工廠模式。
抽象工廠模式是所有形式的工廠模式中最為抽象和最具一般性的一種形態(tài)。
抽象工廠模式與工廠方法模式最大的區(qū)別在于,工廠方法模式針對的是一個產(chǎn)品等級結構,而抽象工廠模式則需要面對多個產(chǎn)品等級結構, 一個工廠等級結構可以負責多個不同產(chǎn)品等級結構中的產(chǎn)品對象的創(chuàng)建 。當一個工廠等級結構可以創(chuàng)建出分屬于不同產(chǎn)品等級結構的一個產(chǎn)品族中的所有對象時, 抽象工廠模式比工廠方法模式更為簡單、有效率。
定義:抽象工廠模式(Abstract Factory Pattern):提供一個創(chuàng)建一系列相關或相互依賴對象的接口,而無須指定它們具體的類。抽象工廠模式又稱為Kit模式,屬于對象創(chuàng)建型模式。
結構:
?AbstractFactory(抽象工廠):它聲明了一組用于創(chuàng)建一族產(chǎn)品的方法,每一個方法對應一種產(chǎn)品。
ConcreteFactory(具體工廠):它實現(xiàn)了在抽象工廠中聲明的創(chuàng)建產(chǎn)品的方法,生成一組具體產(chǎn)品,這些產(chǎn)品構成了一個產(chǎn)品族,每一個產(chǎn)品都位于某個產(chǎn)品等級結構中。
AbstractProduct(抽象產(chǎn)品):它為每種產(chǎn)品聲明接口,在抽象產(chǎn)品中聲明了產(chǎn)品所具有的業(yè)務方法。
ConcreteProduct(具體產(chǎn)品):它定義具體工廠生產(chǎn)的具體產(chǎn)品對象,實現(xiàn)抽象產(chǎn)品接口中聲明的業(yè)務方法。
具體結構圖:
產(chǎn)品類:
public?interface?ProductA{}
public?class?ProductA1implements?ProductA?{
?public?ProductA1(){
System.out.print("create?ProductA1");
}
}
public?class?ProductA2implements?ProductA?{
?public?ProductA2(){
System.out.print("create?ProductA2");
}
}
public?interface?ProductB{}
public?class?ProductB1implements?ProductB?{
?public?ProductB1(){
System.out.print("create?ProductB1");
}
}
public?class?ProductB2implements?ProductB?{
?public?ProductB2(){
System.out.print("create?ProductB2");
}
}
工廠類:
public?interface?abstractFactory?{
?public?ProductA?createProductA();
?public?ProductB?createProductB();
}
public?class?FactoryAimplements?abstractFactory?{
?@Override
? ??public?ProductA?createProductA()?{
?return?new?ProductA1();
}
?@Override
? ??public?ProductB?createProductB()?{
?return?new?ProductB1();
}
}
public?class?FactoryBimplements?abstractFactory?{
?@Override
? ??public?ProductA?createProductA()?{
?return?new?ProductA2();
}
?@Override
? ??public?ProductB?createProductB()?{
?return?new?ProductB2();
}
}
客戶端:
FactoryA?factoryA?=new?FactoryA();
ProductA?productA?=?factoryA.createProductA();
ProductB?productB?=?factoryA.createProductB();
FactoryBfactoryB?=new?FactoryB();
ProductA?producta?=?factoryB.createProductA();
ProductB?productb?=?factoryB.createProductB();
抽象工廠模式優(yōu)點:
抽象工廠模式隔離了具體類的生成,使得客戶并不需要知道什么被創(chuàng)建。由于這種隔離,更換一個具體工廠就變得相對容易。 所有的具體工廠都實現(xiàn)了抽象工廠中定義的那些公共接口,因此只需改變具體工廠的實例,就可以在某種程度上改變整個軟件系統(tǒng)的行為。 另外,應用抽象工廠模式可以實現(xiàn)高內(nèi)聚低耦合的設計目的,因此抽象工廠模式得到了廣泛的應用。
當一個產(chǎn)品族中的多個對象被設計成一起工作時,它能夠保證客戶端始終只使用同一個產(chǎn)品族中的對象。 這對一些需要根據(jù)當前環(huán)境來決定其行為的軟件系統(tǒng)來說,是一種非常實用的設計模式。
增加新的具體工廠和產(chǎn)品族很方便,無須修改已有系統(tǒng),符合“開閉原則”。
抽象工廠模式的缺點:
在添加新的產(chǎn)品對象時,難以擴展抽象工廠來生產(chǎn)新種類的產(chǎn)品,這是因為在抽象工廠角色中規(guī)定了所有可能被創(chuàng)建的產(chǎn)品集合, 要支持新種類的產(chǎn)品就意味著要對該接口進行擴展,而這將涉及到對抽象工廠角色及其所有子類的修改,顯然會帶來較大的不便。
開閉原則的傾斜性(增加新的工廠和產(chǎn)品族容易,增加新的產(chǎn)品等級結構麻煩)。
“開閉原則”的傾斜性:
? ? ? ?1、“開閉原則”要求系統(tǒng)對擴展開放,對修改封閉,通過擴展達到增強其功能的目的。對于涉及到多個產(chǎn)品族與多個產(chǎn)品等級結構的系統(tǒng),其功能增強包括兩方面:
? ? ? ? ? ? ? 增加產(chǎn)品族:對于增加新的產(chǎn)品族,工廠方法模式很好的支持了“開閉原則”,對于新增加的產(chǎn)品族,只需要對應增加一個新的具體工廠即可,對已有代碼無須做任何修改。
? ? ? ? ? ? ? 增加新的產(chǎn)品等級結構:對于增加新的產(chǎn)品等級結構,需要修改所有的工廠角色,包括抽象工廠類,在所有的工廠類中都需要增加生產(chǎn)新產(chǎn)品的方法,不能很好地支持“開閉原則”。
? ? ?? 2、 抽象工廠模式的這種性質稱為“開閉原則”的傾斜性,抽象工廠模式以一種傾斜的方式支持增加新的產(chǎn)品,它為新產(chǎn)品族的增加提供方便,但不能為新的產(chǎn)品等級結構的增加提供這樣的方便。
抽象工廠模式適用環(huán)境:
一個系統(tǒng)不應當依賴于產(chǎn)品類實例如何被創(chuàng)建、組合和表達的細節(jié),這對于所有類型的工廠模式都是重要的。
系統(tǒng)中有多于一個的產(chǎn)品族,而每次只使用其中某一產(chǎn)品族。
屬于同一個產(chǎn)品族的產(chǎn)品將在一起使用,這一約束必須在系統(tǒng)的設計中體現(xiàn)出來。
系統(tǒng)提供一個產(chǎn)品類的庫,所有的產(chǎn)品以同樣的接口出現(xiàn),從而使客戶端不依賴于具體實現(xiàn)。