工廠模式是我們最常用的實例化對象模式了正歼,是用工廠方法代替new操作的一種模式辐马。通常我們所說的工廠模式是指工廠方法模式,它也是使用頻率最高的工廠模式局义。工廠模式在Java程序系統(tǒng)可以說是隨處可見喜爷。因為工廠模式就相當于創(chuàng)建實例對象的new,我們經(jīng)常要根據(jù)類Class生成實例對象萄唇,如A a=new A() 工廠模式也是用來創(chuàng)建實例對象的檩帐,所以以后new時就要多個心眼,是否可以考慮使用工廠模式另萤,雖然這樣做湃密,可能多做一些工作,但會給你系統(tǒng)帶來更大的可擴展性和盡量少的修改量四敞。
工廠模式的作用
工廠模式(包括簡單工廠模式泛源、工廠方法模式和抽象工廠模式)到底有什么用,很多時候通過反射機制就可以很靈活地創(chuàng)建對象目养,為什么還要工廠俩由?
與一個對象有關(guān)的原則有三類:
- 對象本身所具有的職責
- 創(chuàng)建對象的職責
- 使用對象的職責
對象本身的職責很好理解,就是對象自身所具有的一些數(shù)據(jù)和行為癌蚁,可通過一些公開的方法來實現(xiàn)它的職責幻梯。在本文中,我們將簡單討論一下對象的創(chuàng)建職責和使用職責努释。
在Java語言中碘梢,我們通常有以下幾種創(chuàng)建對象的方式:
- 使用new關(guān)鍵字直接創(chuàng)建對象;
- 通過反射機制創(chuàng)建對象伐蒂;
- 通過clone()方法創(chuàng)建對象煞躬;
- 通過工廠類創(chuàng)建對象。
毫無疑問逸邦,在客戶端代碼中直接使用new關(guān)鍵字是最簡單的一種創(chuàng)建對象的方式恩沛,但是它的靈活性較差,下面通過一個簡單的示例來加以說明:
class LoginAction {
private UserDAO udao;
public LoginAction() {
udao = new JDBCUserDAO(); //創(chuàng)建對象
}
public void execute() {
//其他代碼
udao.findUserById(); //使用對象
//其他代碼
}
}
在LoginAction類中定義了一個UserDAO類型的對象udao缕减,在LoginAction的構(gòu)造函數(shù)中創(chuàng)建了JDBCUserDAO類型的udao對象雷客,并在execute()方法中調(diào)用了udao對象的findUserById()方法,這段代碼看上去并沒有什么問題桥狡。下面我們來分析一下LoginAction和UserDAO之間的關(guān)系搅裙,LoginAction類負責創(chuàng)建了一個UserDAO子類的對象并使用UserDAO的方法來完成相應的業(yè)務處理皱卓,也就是說LoginAction即負責udao的創(chuàng)建又負責udao的使用,創(chuàng)建對象和使用對象的職責耦合在一起部逮,這樣的設(shè)計會導致一個很嚴重的問題:如果在LoginAction中希望能夠使用UserDAO的另一個子類如HibernateUserDAO類型的對象娜汁,必須修改LoginAction類的源代碼,違反了“開閉原則”兄朋。如何解決該問題掐禁?
最常用的一種解決方法是將udao對象的創(chuàng)建職責從LoginAction類中移除,在LoginAction類之外創(chuàng)建對象颅和,那么誰來負責創(chuàng)建UserDAO對象呢穆桂?答案是:工廠類。通過引入工廠類融虽,客戶類(如LoginAction)不涉及對象的創(chuàng)建,對象的創(chuàng)建者也不會涉及對象的使用灼芭。引入工廠類UserDAOFactory之后的結(jié)構(gòu)如圖1所示:
工廠類的引入將降低因為產(chǎn)品或工廠類改變所造成的維護工作量有额。如果UserDAO的某個子類的構(gòu)造函數(shù)發(fā)生改變或者要需要添加或移除不同的子類,只要維護UserDAOFactory的代碼彼绷,而不會影響到LoginAction巍佑;如果UserDAO的接口發(fā)生改變,例如添加寄悯、移除方法或改變方法名萤衰,只需要修改LoginAction,不會給UserDAOFactory帶來任何影響猜旬。
在所有的工廠模式中脆栋,我們都強調(diào)一點:兩個類A和B之間的關(guān)系應該僅僅是A創(chuàng)建B或是A使用B,而不能兩種關(guān)系都有洒擦。將對象的創(chuàng)建和使用分離椿争,也使得系統(tǒng)更加符合“單一職責原則”,有利于對功能的復用和系統(tǒng)的維護熟嫩。
此外秦踪,將對象的創(chuàng)建和使用分離還有一個好處:防止用來實例化一個類的數(shù)據(jù)和代碼在多個類中到處都是,可以將有關(guān)創(chuàng)建的知識搬移到一個工廠類中掸茅,這在Joshua Kerievsky的《重構(gòu)與模式》一書中有專門的一節(jié)來進行介紹椅邓。因為有時候我們創(chuàng)建一個對象不只是簡單調(diào)用其構(gòu)造函數(shù),還需要設(shè)置一些參數(shù)昧狮,可能還需要配置環(huán)境景馁,如果將這些代碼散落在每一個創(chuàng)建對象的客戶類中,勢必會出現(xiàn)代碼重復陵且、創(chuàng)建蔓延的問題裁僧,而這些客戶類其實無須承擔對象的創(chuàng)建工作个束,它們只需使用已創(chuàng)建好的對象就可以了。此時聊疲,可以引入工廠類來封裝對象的創(chuàng)建邏輯和客戶代碼的實例化/配置選項塘装。
使用工廠類還有一個“不是特別明顯的”優(yōu)點幔翰,一個類可能擁有多個構(gòu)造函數(shù),而在Java、C#等語言中構(gòu)造函數(shù)名字都與類名相同况鸣,客戶端只能通過傳入不同的參數(shù)來調(diào)用不同的構(gòu)造函數(shù)創(chuàng)建對象,從構(gòu)造函數(shù)和參數(shù)列表中也許大家根本不了解不同構(gòu)造函數(shù)所構(gòu)造的產(chǎn)品的差異忙厌。但如果將對象的創(chuàng)建過程封裝在工廠類中铃岔,我們可以提供一系列名字完全不同的工廠方法,每一個工廠方法對應一個構(gòu)造函數(shù)门岔,客戶端可以以一種更加可讀爱致、易懂的方式來創(chuàng)建對象,而且寒随,從一組工廠方法中選擇一個意義明確的工廠方法糠悯,比從一組名稱相同參數(shù)不同的構(gòu)造函數(shù)中選擇一個構(gòu)造函數(shù)要方便很多。
那么妻往,有人可能會問互艾,是否需要為設(shè)計中的每一個類都配備一個工廠類?答案是:具體情況具體分析讯泣。如果產(chǎn)品類很簡單纫普,而且不存在太多變數(shù),其構(gòu)造過程也很簡單好渠,此時無須為其提供工廠類昨稼,直接在使用之前實例化即可,例如Java語言中的String類晦墙,我們就無須為它專門提供一個StringFactory悦昵,這樣做反而有點像殺雞用牛刀,大材小用晌畅,而且會導致工廠泛濫但指,增加系統(tǒng)的復雜度。
工廠模式是為了將對象的創(chuàng)建和使用分離抗楔,也使得系統(tǒng)更加符合“單一職責原則”棋凳,有利于對功能的復用和系統(tǒng)的維護,防止用來實例化一個類的數(shù)據(jù)和代碼在多個類中到處都是连躏,可以將有關(guān)創(chuàng)建的知識搬移到一個工廠類中剩岳。
轉(zhuǎn)載:創(chuàng)建對象與使用對象——談談工廠的作用
簡單工廠模式
簡單工廠模式(Simple Factory Pattern):定義一個工廠類,它可以根據(jù)參數(shù)的不同返回不同類的實例入热,被創(chuàng)建的實例通常都具有共同的父類拍棕。因為在簡單工廠模式中用于創(chuàng)建實例的方法是靜態(tài)(static)方法晓铆,因此簡單工廠模式又被稱為靜態(tài)工廠方法(Static Factory Method)模式,它屬于類創(chuàng)建型模式绰播。
簡單工廠模式的要點在于:當你需要什么骄噪,只需要傳入一個正確的參數(shù),就可以獲取你所需要的對象蠢箩,而無須知道其創(chuàng)建細節(jié)链蕊。簡單工廠模式結(jié)構(gòu)比較簡單,其核心是工廠類的設(shè)計, 其結(jié)構(gòu)如下圖所示谬泌。
在簡單工廠模式結(jié)構(gòu)圖中包含如下幾個角色:
- Factory(工廠角色):工廠角色即工廠類滔韵,它是簡單工廠模式的核心,負責實現(xiàn)創(chuàng)建所有產(chǎn)品實例的內(nèi)部邏輯掌实;工廠類可以被外界直接調(diào)用陪蜻,創(chuàng)建所需的產(chǎn)品對象;在工廠類中提供了靜態(tài)的工廠方法factoryMethod()贱鼻,它的返回類型為抽象產(chǎn)品類型Product囱皿。
- Product(抽象產(chǎn)品角色):它是工廠類所創(chuàng)建的所有對象的父類,封裝了各種產(chǎn)品對象的公有方法忱嘹,它的引入將提高系統(tǒng)的靈活性,使得在工廠類中只需定義一個通用的工廠方法耕渴,因為所有創(chuàng)建的具體產(chǎn)品對象都是其子類對象拘悦。
- ConcreteProduct(具體產(chǎn)品角色):它是簡單工廠模式的創(chuàng)建目標,所有被創(chuàng)建的對象都充當這個角色的某個具體類的實例橱脸。每一個具體產(chǎn)品角色都繼承了抽象產(chǎn)品角色础米,需要實現(xiàn)在抽象產(chǎn)品中聲明的抽象方法。
在簡單工廠模式中添诉,客戶端通過工廠類來創(chuàng)建一個產(chǎn)品類的實例屁桑,而無須直接使用new關(guān)鍵字來創(chuàng)建對象,它是工廠模式家族中最簡單的一員栏赴。
在使用簡單工廠模式時蘑斧,首先需要對產(chǎn)品類進行重構(gòu),不能設(shè)計一個包羅萬象的產(chǎn)品類须眷,而需根據(jù)實際情況設(shè)計一個產(chǎn)品層次結(jié)構(gòu)竖瘾,將所有產(chǎn)品類公共的代碼移至抽象產(chǎn)品類,并在抽象產(chǎn)品類中聲明一些抽象方法花颗,以供不同的具體產(chǎn)品類來實現(xiàn)捕传,典型的抽象產(chǎn)品類代碼如下所示:
abstract class Product {
//所有產(chǎn)品類的公共業(yè)務方法
public void methodSame() {
//公共方法的實現(xiàn)
}
//聲明抽象業(yè)務方法
public abstract void methodDiff();
}
在具體產(chǎn)品類中實現(xiàn)了抽象產(chǎn)品類中聲明的抽象業(yè)務方法,不同的具體產(chǎn)品類可以提供不同的實現(xiàn)扩劝,典型的具體產(chǎn)品類代碼如下所示:
class ConcreteProduct extends Product {
//實現(xiàn)業(yè)務方法
public void methodDiff() {
//業(yè)務方法的實現(xiàn)
}
}
簡單工廠模式的核心是工廠類庸论,在沒有工廠類之前职辅,客戶端一般會使用new關(guān)鍵字來直接創(chuàng)建產(chǎn)品對象,而在引入工廠類之后聂示,客戶端可以通過工廠類來創(chuàng)建產(chǎn)品域携,在簡單工廠模式中,工廠類提供了一個靜態(tài)工廠方法供客戶端使用催什,根據(jù)所傳入的參數(shù)不同可以創(chuàng)建不同的產(chǎn)品對象涵亏,典型的工廠類代碼如下所示:
class Factory {
//靜態(tài)工廠方法
public static Product getProduct(String arg) {
Product product = null;
if (arg.equalsIgnoreCase("A")) {
product = new ConcreteProductA();
//初始化設(shè)置product
}
else if (arg.equalsIgnoreCase("B")) {
product = new ConcreteProductB();
//初始化設(shè)置product
}
return product;
}
}
在客戶端代碼中,我們通過調(diào)用工廠類的工廠方法即可得到產(chǎn)品對象蒲凶,典型代碼如下所示:
class Client {
public static void main(String args[]) {
Product product;
product = Factory.getProduct("A"); //通過工廠類創(chuàng)建產(chǎn)品對象
product.methodSame();
product.methodDiff();
}
}
簡單工廠模式總結(jié):
簡單工廠模式提供了專門的工廠類用于創(chuàng)建對象气筋,將對象的創(chuàng)建和對象的使用分離開,它作為一種最簡單的工廠模式在軟件開發(fā)中得到了較為廣泛的應用旋圆。
-
優(yōu)點:
- 工廠類包含必要的判斷邏輯宠默,可以決定在什么時候創(chuàng)建哪一個產(chǎn)品類的實例,客戶端可以免除直接創(chuàng)建產(chǎn)品對象的職責灵巧,而僅僅“消費”產(chǎn)品搀矫,簡單工廠模式實現(xiàn)了對象創(chuàng)建和使用的分離。
- 客戶端無須知道所創(chuàng)建的具體產(chǎn)品類的類名刻肄,只需要知道具體產(chǎn)品類所對應的參數(shù)即可瓤球,對于一些復雜的類名,通過簡單工廠模式可以在一定程度減少使用者的記憶量敏弃。
- 通過引入配置文件卦羡,可以在不修改任何客戶端代碼的情況下更換和增加新的具體產(chǎn)品類,在一定程度上提高了系統(tǒng)的靈活性麦到。
-
缺點:
- 由于工廠類集中了所有產(chǎn)品的創(chuàng)建邏輯绿饵,職責過重,一旦不能正常工作瓶颠,整個系統(tǒng)都要受到影響拟赊。
- 使用簡單工廠模式勢必會增加系統(tǒng)中類的個數(shù)(引入了新的工廠類),增加了系統(tǒng)的復雜度和理解難度粹淋。
- 系統(tǒng)擴展困難吸祟,一旦添加新產(chǎn)品就不得不修改工廠邏輯,在產(chǎn)品類型較多時桃移,有可能造成工廠邏輯過于復雜欢搜,不利于系統(tǒng)的擴展和維護。
- 系統(tǒng)擴展困難谴轮,一旦添加新產(chǎn)品就不得不修改工廠邏輯炒瘟,在產(chǎn)品類型較多時,有可能造成工廠邏輯過于復雜第步,不利于系統(tǒng)的擴展和維護疮装。
-
適用場景:
- 工廠類負責創(chuàng)建的對象比較少缘琅,由于創(chuàng)建的對象較少,不會造成工廠方法中的業(yè)務邏輯太過復雜廓推。
- 工廠類負責創(chuàng)建的對象比較少刷袍,由于創(chuàng)建的對象較少,不會造成工廠方法中的業(yè)務邏輯太過復雜樊展。
工廠方法模式
簡單工廠模式雖然簡單呻纹,但存在一個很嚴重的問題。當系統(tǒng)中需要引入新產(chǎn)品時专缠,由于靜態(tài)工廠方法通過所傳入?yún)?shù)的不同來創(chuàng)建不同的產(chǎn)品雷酪,這必定要修改工廠類的源代碼,將違背“開閉原則”涝婉,如何實現(xiàn)增加新產(chǎn)品而不影響已有代碼哥力?工廠方法模式應運而生.
在工廠方法模式中,我們不再提供一個統(tǒng)一的工廠類來創(chuàng)建所有的產(chǎn)品對象墩弯,而是針對不同的產(chǎn)品提供不同的工廠吩跋,系統(tǒng)提供一個與產(chǎn)品等級結(jié)構(gòu)對應的工廠等級結(jié)構(gòu)。
工廠方法模式(Factory Method Pattern):定義一個用于創(chuàng)建對象的接口渔工,讓子類決定將哪一個類實例化锌钮。工廠方法模式讓一個類的實例化延遲到其子類。工廠方法模式又簡稱為工廠模式(Factory Pattern)引矩,又可稱作虛擬構(gòu)造器模式(Virtual Constructor Pattern)或多態(tài)工廠模式(Polymorphic Factory Pattern)轧粟。工廠方法模式是一種類創(chuàng)建型模式。
工廠方法模式提供一個抽象工廠接口來聲明抽象工廠方法脓魏,而由其子類來具體實現(xiàn)工廠方法,創(chuàng)建具體的產(chǎn)品對象通惫。工廠方法模式結(jié)構(gòu)如圖所示:
在工廠方法模式結(jié)構(gòu)圖中包含如下幾個角色:
- Product(抽象產(chǎn)品):它是定義產(chǎn)品的接口茂翔,是工廠方法模式所創(chuàng)建對象的超類型,也就是產(chǎn)品對象的公共父類履腋。
- ConcreteProduct(具體產(chǎn)品):它實現(xiàn)了抽象產(chǎn)品接口珊燎,某種類型的具體產(chǎn)品由專門的具體工廠創(chuàng)建,具體工廠和具體產(chǎn)品之間一一對應遵湖。
- Factory(抽象工廠):在抽象工廠類中悔政,聲明了工廠方法(Factory Method),用于返回一個產(chǎn)品延旧。抽象工廠是工廠方法模式的核心谋国,所有創(chuàng)建對象的工廠類都必須實現(xiàn)該接口。
- ConcreteFactory(具體工廠):它是抽象工廠類的子類迁沫,實現(xiàn)了抽象工廠中定義的工廠方法芦瘾,并可由客戶端調(diào)用捌蚊,返回一個具體產(chǎn)品類的實例。
與簡單工廠模式相比近弟,工廠方法模式最重要的區(qū)別是引入了抽象工廠角色缅糟,抽象工廠可以是接口,也可以是抽象類或者具體類祷愉,其典型代碼如下所示:
interface Factory {
public Product factoryMethod();
}
在實際使用時窗宦,具體工廠類在實現(xiàn)工廠方法時除了創(chuàng)建具體產(chǎn)品對象之外,還可以負責產(chǎn)品對象的初始化工作以及一些資源和環(huán)境配置工作二鳄,例如連接數(shù)據(jù)庫赴涵、創(chuàng)建文件等。
在客戶端代碼中泥从,只需關(guān)心工廠類即可句占,不同的具體工廠可以創(chuàng)建不同的產(chǎn)品,典型的客戶端類代碼片段如下所示:
Factory factory;
factory = new ConcreteFactory(); //可以結(jié)合配置文件和反射機制來實現(xiàn)
Product product;
product = factory.factoryMethod();
可以通過配置文件來存儲具體工廠類ConcreteFactory的類名躯嫉,更換新的具體工廠時無須修改源代碼纱烘,系統(tǒng)擴展更為方便。
工廠方法模式總結(jié)
-
優(yōu)點
- 在工廠方法模式中祈餐,工廠方法用來創(chuàng)建客戶所需要的產(chǎn)品擂啥,同時還向客戶隱藏了哪種具體產(chǎn)品類將被實例化這一細節(jié),用戶只需要關(guān)心所需產(chǎn)品對應的工廠帆阳,無須關(guān)心創(chuàng)建細節(jié)哺壶,甚至無須知道具體產(chǎn)品類的類名。
- 基于工廠角色和產(chǎn)品角色的多態(tài)性設(shè)計是工廠方法模式的關(guān)鍵蜒谤。它能夠讓工廠可以自主確定創(chuàng)建何種產(chǎn)品對象山宾,而如何創(chuàng)建這個對象的細節(jié)則完全封裝在具體工廠內(nèi)部。工廠方法模式之所以又被稱為多態(tài)工廠模式鳍徽,就正是因為所有的具體工廠類都具有同一抽象父類资锰。
- 使用工廠方法模式的另一個優(yōu)點是在系統(tǒng)中加入新產(chǎn)品時,無須修改抽象工廠和抽象產(chǎn)品提供的接口阶祭,無須修改客戶端绷杜,也無須修改其他的具體工廠和具體產(chǎn)品,而只要添加一個具體工廠和具體產(chǎn)品就可以了濒募,這樣鞭盟,系統(tǒng)的可擴展性也就變得非常好,完全符合“開閉原則”瑰剃。
-
缺點
- 在添加新產(chǎn)品時齿诉,需要編寫新的具體產(chǎn)品類,而且還要提供與之對應的具體工廠類,系統(tǒng)中類的個數(shù)將成對增加鹃两,在一定程度上增加了系統(tǒng)的復雜度遗座,有更多的類需要編譯和運行,會給系統(tǒng)帶來一些額外的開銷俊扳。
- 由于考慮到系統(tǒng)的可擴展性途蒋,需要引入抽象層,在客戶端代碼中均使用抽象層進行定義馋记,增加了系統(tǒng)的抽象性和理解難度号坡,且在實現(xiàn)時可能需要用到DOM、反射等技術(shù)梯醒,增加了系統(tǒng)的實現(xiàn)難度宽堆。
-
適用場景
- 客戶端不知道它所需要的對象的類。在工廠方法模式中茸习,客戶端不需要知道具體產(chǎn)品類的類名畜隶,只需要知道所對應的工廠即可,具體的產(chǎn)品對象由具體工廠類創(chuàng)建号胚,可將具體工廠類的類名存儲在配置文件或數(shù)據(jù)庫中籽慢。
- 抽象工廠類通過其子類來指定創(chuàng)建哪個對象。在工廠方法模式中猫胁,對于抽象工廠類只需要提供一個創(chuàng)建產(chǎn)品的接口箱亿,而由其子類來確定具體要創(chuàng)建的對象,利用面向?qū)ο蟮亩鄳B(tài)性和里氏代換原則弃秆,在程序運行時届惋,子類對象將覆蓋父類對象,從而使得系統(tǒng)更容易擴展菠赚。
抽象工廠模式
抽象工廠模式(Abstract Factory Pattern):提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口脑豹,而無須指定它們具體的類。抽象工廠模式又稱為Kit模式衡查,它是一種對象創(chuàng)建型模式瘩欺。
在抽象工廠模式中,每一個具體工廠都提供了多個工廠方法用于產(chǎn)生多種不同類型的產(chǎn)品峡捡,這些產(chǎn)品構(gòu)成了一個產(chǎn)品族,抽象工廠模式結(jié)構(gòu)如圖所示:
在抽象工廠模式結(jié)構(gòu)圖中包含如下幾個角色:
- AbstractFactory(抽象工廠):它聲明了一組用于創(chuàng)建一族產(chǎn)品的方法筑悴,每一個方法對應一種產(chǎn)品们拙。
- ConcreteFactory(具體工廠):它實現(xiàn)了在抽象工廠中聲明的創(chuàng)建產(chǎn)品的方法,生成一組具體產(chǎn)品阁吝,這些產(chǎn)品構(gòu)成了一個產(chǎn)品族砚婆,每一個產(chǎn)品都位于某個產(chǎn)品等級結(jié)構(gòu)中。
- AbstractProduct(抽象產(chǎn)品):它為每種產(chǎn)品聲明接口,在抽象產(chǎn)品中聲明了產(chǎn)品所具有的業(yè)務方法装盯。
- ConcreteProduct(具體產(chǎn)品):它定義具體工廠生產(chǎn)的具體產(chǎn)品對象坷虑,實現(xiàn)抽象產(chǎn)品接口中聲明的業(yè)務方法。
在抽象工廠中聲明了多個工廠方法埂奈,用于創(chuàng)建不同類型的產(chǎn)品迄损,抽象工廠可以是接口,也可以是抽象類或者具體類账磺,其典型代碼如下所示:
class ConcreteFactory1 extends AbstractFactory {
//工廠方法一
public AbstractProductA createProductA() {
return new ConcreteProductA1();
}
//工廠方法二
public AbstractProductB createProductB() {
return new ConcreteProductB1();
}
……
}
與工廠方法模式一樣芹敌,抽象工廠模式也可為每一種產(chǎn)品提供一組重載的工廠方法,以不同的方式對產(chǎn)品對象進行創(chuàng)建垮抗。
具體工廠實現(xiàn)了抽象工廠氏捞,每一個具體的工廠方法可以返回一個特定的產(chǎn)品對象,而同一個具體工廠所創(chuàng)建的產(chǎn)品對象構(gòu)成了一個產(chǎn)品族冒版。
開閉原則”的傾斜性
在抽象工廠模式中液茎,增加新的產(chǎn)品族很方便,但是增加新的產(chǎn)品等級結(jié)構(gòu)很麻煩辞嗡,抽象工廠模式的這種性質(zhì)稱為“開閉原則”的傾斜性捆等。“開閉原則”要求系統(tǒng)對擴展開放,對修改封閉欲间,通過擴展達到增強其功能的目的楚里,對于涉及到多個產(chǎn)品族與多個產(chǎn)品等級結(jié)構(gòu)的系統(tǒng),其功能增強包括兩方面:
- 增加產(chǎn)品族:對于增加新的產(chǎn)品族猎贴,抽象工廠模式很好地支持了“開閉原則”班缎,只需要增加具體產(chǎn)品并對應增加一個新的具體工廠,對已有代碼無須做任何修改她渴。
- 加新的產(chǎn)品等級結(jié)構(gòu):對于增加新的產(chǎn)品等級結(jié)構(gòu)达址,需要修改所有的工廠角色,包括抽象工廠類趁耗,在所有的工廠類中都需要增加生產(chǎn)新產(chǎn)品的方法沉唠,違背了“開閉原則”。
正因為抽象工廠模式存在“開閉原則”的傾斜性苛败,它以一種傾斜的方式來滿足“開閉原則”满葛,為增加新產(chǎn)品族提供方便,但不能為增加新產(chǎn)品結(jié)構(gòu)提供這樣的方便罢屈,因此要求設(shè)計人員在設(shè)計之初就能夠全面考慮嘀韧,不會在設(shè)計完成之后向系統(tǒng)中增加新的產(chǎn)品等級結(jié)構(gòu),也不會刪除已有的產(chǎn)品等級結(jié)構(gòu)缠捌,否則將會導致系統(tǒng)出現(xiàn)較大的修改锄贷,為后續(xù)維護工作帶來諸多麻煩。
抽象工廠模式總結(jié)
-
優(yōu)點
- 抽象工廠模式隔離了具體類的生成,使得客戶并不需要知道什么被創(chuàng)建谊却。由于這種隔離柔昼,更換一個具體工廠就變得相對容易,所有的具體工廠都實現(xiàn)了抽象工廠中定義的那些公共接口炎辨,因此只需改變具體工廠的實例捕透,就可以在某種程度上改變整個軟件系統(tǒng)的行為。
- 當一個產(chǎn)品族中的多個對象被設(shè)計成一起工作時蹦魔,它能夠保證客戶端始終只使用同一個產(chǎn)品族中的對象激率。
- 增加新的產(chǎn)品族很方便,無須修改已有系統(tǒng)勿决,符合“開閉原則”乒躺。
-
缺點
- 增加新的產(chǎn)品等級結(jié)構(gòu)麻煩,需要對原有系統(tǒng)進行較大的修改低缩,甚至需要修改抽象層代碼嘉冒,這顯然會帶來較大的不便,違背了“開閉原則”咆繁。
-
適用場景
- 一個系統(tǒng)不應當依賴于產(chǎn)品類實例如何被創(chuàng)建讳推、組合和表達的細節(jié),這對于所有類型的工廠模式都是很重要的玩般,用戶無須關(guān)心對象的創(chuàng)建過程银觅,將對象的創(chuàng)建和使用解耦。
- 系統(tǒng)中有多于一個的產(chǎn)品族坏为,而每次只使用其中某一產(chǎn)品族究驴。可以通過配置文件等方式來使得用戶可以動態(tài)改變產(chǎn)品族匀伏,也可以很方便地增加新的產(chǎn)品族洒忧。
- 屬于同一個產(chǎn)品族的產(chǎn)品將在一起使用,這一約束必須在系統(tǒng)的設(shè)計中體現(xiàn)出來够颠。同一個產(chǎn)品族中的產(chǎn)品可以是沒有任何關(guān)系的對象熙侍,但是它們都具有一些共同的約束,如同一操作系統(tǒng)下的按鈕和文本框履磨,按鈕與文本框之間沒有直接關(guān)系蛉抓,但它們都是屬于某一操作系統(tǒng)的,此時具有一個共同的約束條件:操作系統(tǒng)的類型剃诅。
- 產(chǎn)品等級結(jié)構(gòu)穩(wěn)定巷送,設(shè)計完成之后,不會向系統(tǒng)中增加新的產(chǎn)品等級結(jié)構(gòu)或者刪除已有的產(chǎn)品等級結(jié)構(gòu)综苔。