定義
- 工廠方法模式是類的創(chuàng)建模式,又叫虛擬構(gòu)造器(Virtual Constructor)模式,或者多態(tài)性工廠模式冤吨。
- 定義一個(gè)創(chuàng)建對(duì)象的接口,讓子類決定實(shí)例化哪一個(gè)類饶套。工廠方法使一個(gè)類的實(shí)例化延遲到其子類漩蟆。
結(jié)構(gòu)
工廠方法包含了一下角色
- Product:抽象產(chǎn)品
- ConcreteProduct:具象產(chǎn)品
- Factory:抽象工廠
- ConcreteFactory:具象工廠
場(chǎng)景示例
還是拿售賣機(jī)票舉例,我們之前用簡(jiǎn)單工廠實(shí)現(xiàn)了不同供應(yīng)商的下單邏輯凤跑,但是隨著業(yè)務(wù)的不斷擴(kuò)大爆安,我們對(duì)接的供應(yīng)商越來(lái)越多,這樣就會(huì)造成每次對(duì)接一個(gè)供應(yīng)商都會(huì)在工廠類中添加分支仔引,對(duì)工廠類進(jìn)行修改扔仓,這就違反了開(kāi)閉原則
,所以現(xiàn)在我們用工廠方法來(lái)修改一下咖耘。
Factory 代碼
public interface Factory {
Product createProduct();
}
public class AFactory implements Factory {
@Override
public Product createProduct() {
return new AProduct();
}
}
public class BFactory implements Factory {
@Override
public Product createProduct() {
return new BProduct();
}
}
public class CFactory implements Factory {
@Override
public Product createProduct() {
return new CProdut();
}
}
... D
... E
Product代碼
public interface Product {
void createOrder();
}
public class AProduct implements Product {
@Override
public void createOrder() {
System.out.println("供應(yīng)商A:下單操作");
}
}
public class BProduct implements Product {
@Override
public void createOrder() {
System.out.println("供應(yīng)商B:下單操作");
}
}
public class CProdut implements Product {
@Override
public void createOrder() {
System.out.println("供應(yīng)商B:下單操作");
}
}
... D
... E
Client 代碼
public class Client {
public static void main(String[] args) {
Factory aFactory = new AFactory();
Product aProduct = aFactory.createProduct();
aProduct.createOrder();
Factory bFactory = new BFactory();
Product bProduct = bFactory.createProduct();
bProduct.createOrder();
}
}
輸出供應(yīng)商A:下單操作 供應(yīng)商B:下單操作
以上就是一個(gè)簡(jiǎn)單的工廠方法的實(shí)現(xiàn)翘簇。即使在添加新的供應(yīng)商,我們只要?jiǎng)?chuàng)建新的供應(yīng)商工廠以及其實(shí)現(xiàn)就可以了儿倒,這樣對(duì)我們的整個(gè)的工廠和產(chǎn)品體系都沒(méi)有發(fā)生修改版保,而只是擴(kuò)展了變化,這就完全符合了開(kāi)放-閉合
原則夫否。如果我們的需求發(fā)生了變化彻犁,要同時(shí)支持單程、往返的下單凰慈,只要我們?cè)诿恳粋€(gè)供應(yīng)商作為一個(gè)簡(jiǎn)單工廠汞幢,創(chuàng)建出支持單程、往返的兩種具象的產(chǎn)品就可以了微谓。但是我們仔細(xì)觀察就能發(fā)現(xiàn)森篷,工廠方法模式實(shí)現(xiàn)時(shí)输钩,客戶端需要決定實(shí)例化哪一個(gè)工廠,選擇判斷的問(wèn)題還是存在的仲智,也就是說(shuō)买乃,工廠方法把簡(jiǎn)單工廠的內(nèi)部邏輯判斷移到了客戶端代碼來(lái)運(yùn)行,你想要什么功能钓辆,本來(lái)是去修改工廠的剪验,但是現(xiàn)在是去修改了客戶端!
此例只是針對(duì)每個(gè)工廠只生成一個(gè)具象產(chǎn)品類岩馍,至于一個(gè)工廠生成多個(gè)具象產(chǎn)品類可將每個(gè)工廠改造成簡(jiǎn)單工廠碉咆,具體可參考
披薩店
。
消除分支判斷可以利用反射
的方法蛀恩。(將在抽象工廠章節(jié)統(tǒng)一列出)
優(yōu)點(diǎn)
在工廠方法模式中疫铜,工廠方法用來(lái)創(chuàng)建客戶端需要的產(chǎn)品,同時(shí)還向客戶端隱藏了哪種具體產(chǎn)品類將被實(shí)例化這一細(xì)節(jié)双谆,客戶端只用關(guān)心產(chǎn)品對(duì)應(yīng)的工廠壳咕,無(wú)需關(guān)心創(chuàng)建細(xì)節(jié),甚至無(wú)需知道具體產(chǎn)品的類名顽馋。
面向接口編程
谓厘,基于工廠角色和產(chǎn)品角色的多態(tài)性設(shè)計(jì)是工廠方法模式的關(guān)鍵。它能夠使工廠可以自主確定創(chuàng)建何種產(chǎn)品對(duì)象寸谜,而如何創(chuàng)建這個(gè)對(duì)象的細(xì)節(jié)則完全封裝在具體工廠內(nèi)部竟稳。工廠方法模式之所以又被稱為多態(tài)工廠模式,是因?yàn)樗械木唧w工廠類都具有同一抽象父類熊痴。遵循
開(kāi)放-閉合
原則他爸,在系統(tǒng)中新增加一個(gè)產(chǎn)品時(shí),不用更改抽象工廠以及抽象產(chǎn)品果善,也不用對(duì)客戶端以及具象工廠和產(chǎn)品做修改诊笤,而只要添加一個(gè)具體工廠和具體產(chǎn)品就可以了。
缺點(diǎn)
在添加新產(chǎn)品時(shí)巾陕,需要編寫(xiě)新的具體產(chǎn)品類讨跟,而且還要提供與之對(duì)應(yīng)的具體工廠類,系統(tǒng)中類的個(gè)數(shù)將成對(duì)增加鄙煤,在一定程度上增加了系統(tǒng)的復(fù)雜度晾匠,有更多的類需要編譯和運(yùn)行,會(huì)給系統(tǒng)帶來(lái)一些額外的開(kāi)銷梯刚。
由于考慮到系統(tǒng)的可擴(kuò)展性混聊,需要引入抽象層,在客戶端代碼中均使用抽象層進(jìn)行定義,增加了系統(tǒng)的抽象性和理解難度句喜,且在實(shí)現(xiàn)時(shí)可能需要用到DOM、反射等技術(shù)沟于,增加了系統(tǒng)的實(shí)現(xiàn)難度咳胃。
應(yīng)用場(chǎng)景
一個(gè)類不知道它所需要的對(duì)象的類:在工廠方法模式中,客戶端不需要知道具體產(chǎn)品類的類名旷太,只需要知道所對(duì)應(yīng)的工廠即可展懈,具體的產(chǎn)品對(duì)象由具體工廠類創(chuàng)建;客戶端需要知道創(chuàng)建具體產(chǎn)品的工廠類供璧。
一個(gè)類通過(guò)其子類來(lái)指定創(chuàng)建哪個(gè)對(duì)象:在工廠方法模式中存崖,對(duì)于抽象工廠類只需要提供一個(gè)創(chuàng)建產(chǎn)品的接口,而由其子類來(lái)確定具體要?jiǎng)?chuàng)建的對(duì)象睡毒,利用面向?qū)ο蟮亩鄳B(tài)性和里氏代換原則来惧,在程序運(yùn)行時(shí),子類對(duì)象將覆蓋父類對(duì)象演顾,從而使得系統(tǒng)更容易擴(kuò)展供搀。
將創(chuàng)建對(duì)象的任務(wù)委托給多個(gè)工廠子類中的某一個(gè),客戶端在使用時(shí)可以無(wú)須關(guān)心是哪一個(gè)工廠子類創(chuàng)建產(chǎn)品子類钠至,需要時(shí)再動(dòng)態(tài)指定葛虐,可將具體工廠類的類名存儲(chǔ)在配置文件或數(shù)據(jù)庫(kù)中。
擴(kuò)展
- 使用多個(gè)工廠方法棉钧,可在抽象工廠中定義多個(gè)工廠方法屿脐,從而使具體工廠實(shí)現(xiàn)不同的工廠方法,哲學(xué)工廠方法包含不同的邏輯宪卿,創(chuàng)建不同的產(chǎn)品(抽象工廠)
- 產(chǎn)品對(duì)象的重復(fù)使用:
(1)工廠對(duì)象將已經(jīng)創(chuàng)建過(guò)的產(chǎn)品保存到一個(gè)集合(如數(shù)組的诵、List等)中,然后根據(jù)客戶對(duì)產(chǎn)品的請(qǐng)求愧捕,對(duì)集合進(jìn)行查詢奢驯。如果有滿足要求的產(chǎn)品對(duì)象,就直接將該產(chǎn)品返回客戶端次绘;如果集合中沒(méi)有這樣的產(chǎn)品對(duì)象瘪阁,那么就創(chuàng)建一個(gè)新的滿足要求的產(chǎn)品對(duì)象,然后將這個(gè)對(duì)象在增加到集合中邮偎,再返回給客戶端管跺。
(2)Spring單例模式的使用- 多態(tài)性的喪失和模式的退化:如果工廠僅僅返回一個(gè)具體產(chǎn)品對(duì)象,便違背了工廠方法的用意禾进,發(fā)生退化豁跑,此時(shí)就不再是工廠方法模式了。一般來(lái)說(shuō)泻云,工廠對(duì)象應(yīng)當(dāng)有一個(gè)抽象的父類型艇拍,如果工廠等級(jí)結(jié)構(gòu)中只有一個(gè)具體工廠類的話狐蜕,抽象工廠就可以省略,也將發(fā)生了退化卸夕。當(dāng)只有一個(gè)具體工廠层释,在具體工廠中可以創(chuàng)建所有的產(chǎn)品對(duì)象,并且工廠方法設(shè)計(jì)為靜態(tài)方法時(shí)快集,工廠方法模式就退化成簡(jiǎn)單工廠模式贡羔。(本例就可以簡(jiǎn)化為簡(jiǎn)單工廠模式)
總結(jié)
工廠方法模式又稱為
工廠模式
,虛擬構(gòu)造器
模式个初。工廠方法中父類負(fù)責(zé)定義創(chuàng)建產(chǎn)品的統(tǒng)一接口乖寒,工廠子類負(fù)責(zé)生成具體的產(chǎn)品類。將產(chǎn)品的實(shí)例化操作延遲到子類進(jìn)行院溺,由子類決定實(shí)例化哪一個(gè)具體的產(chǎn)品類楣嘁。工廠方法模式包含四個(gè)角色:抽象工廠、具象工廠覆获、抽象產(chǎn)品马澈、具象產(chǎn)品
工廠方法模式是簡(jiǎn)單工廠的進(jìn)一步的抽象和推廣,它們都是集中封裝了對(duì)象的創(chuàng)建弄息,使得更換對(duì)象時(shí)不需要做大的改動(dòng)就可以實(shí)現(xiàn)痊班,降低了客戶端程序與產(chǎn)品對(duì)象的耦合。但是由于工廠方法模式使用了多態(tài)性摹量,工廠方法模式保持了簡(jiǎn)單工廠模式的有點(diǎn)涤伐,而且克服了它的缺點(diǎn)。
工廠方法模式的主要優(yōu)點(diǎn)是增加新的產(chǎn)品類時(shí)無(wú)須修改現(xiàn)有系統(tǒng)缨称,并封裝了產(chǎn)品對(duì)象的創(chuàng)建細(xì)節(jié)凝果,系統(tǒng)具有良好的靈活性和可擴(kuò)展性;其缺點(diǎn)在于增加新產(chǎn)品的同時(shí)需要增加新的工廠睦尽,導(dǎo)致系統(tǒng)類的個(gè)數(shù)成對(duì)增加器净,在一定程度上增加了系統(tǒng)的復(fù)雜性。
工廠方法模式適用情況包括:一個(gè)類不知道它所需要的對(duì)象的類当凡;一個(gè)類通過(guò)其子類來(lái)指定創(chuàng)建哪個(gè)對(duì)象山害;將創(chuàng)建對(duì)象的任務(wù)委托給多個(gè)工廠子類中的某一個(gè),客戶端在使用時(shí)可以無(wú)須關(guān)心是哪一個(gè)工廠子類創(chuàng)建產(chǎn)品子類沿量,需要時(shí)再動(dòng)態(tài)指定浪慌。