設(shè)計(jì)模式 - 工廠方法模式

定義

  • 工廠方法模式是類的創(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)指定浪慌。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市朴则,隨后出現(xiàn)的幾起案子权纤,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件汹想,死亡現(xiàn)場(chǎng)離奇詭異外邓,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)欧宜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門(mén)坐榆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人冗茸,你說(shuō)我怎么就攤上這事∑ブ校” “怎么了夏漱?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)顶捷。 經(jīng)常有香客問(wèn)我挂绰,道長(zhǎng),這世上最難降的妖魔是什么服赎? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任葵蒂,我火速辦了婚禮,結(jié)果婚禮上重虑,老公的妹妹穿的比我還像新娘践付。我一直安慰自己,他們只是感情好缺厉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布永高。 她就那樣靜靜地躺著,像睡著了一般提针。 火紅的嫁衣襯著肌膚如雪命爬。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,763評(píng)論 1 307
  • 那天辐脖,我揣著相機(jī)與錄音饲宛,去河邊找鬼。 笑死嗜价,一個(gè)胖子當(dāng)著我的面吹牛艇抠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播炭剪,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼练链,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了奴拦?” 一聲冷哼從身側(cè)響起媒鼓,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后绿鸣,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體疚沐,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年潮模,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了亮蛔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡擎厢,死狀恐怖究流,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情动遭,我是刑警寧澤芬探,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站厘惦,受9級(jí)特大地震影響偷仿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜宵蕉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一酝静、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧羡玛,春花似錦鸽凶、人聲如沸桌硫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)阻问。三九已至皇钞,卻和暖如春跨细,著一層夾襖步出監(jiān)牢的瞬間砚偶,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工是越, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留耳舅,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓倚评,卻偏偏與公主長(zhǎng)得像浦徊,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子天梧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 設(shè)計(jì)模式概述 在學(xué)習(xí)面向?qū)ο笃叽笤O(shè)計(jì)原則時(shí)需要注意以下幾點(diǎn):a) 高內(nèi)聚盔性、低耦合和單一職能的“沖突”實(shí)際上,這兩者...
    彥幀閱讀 3,748評(píng)論 0 14
  • 設(shè)計(jì)原則: 要依賴抽象呢岗,不要依賴具體類 目錄 本文的結(jié)構(gòu)如下: 什么是工廠方法模式 為什么要用該模式 模式的結(jié)構(gòu) ...
    w1992wishes閱讀 1,344評(píng)論 0 6
  • 工廠方法模式 介紹 簡(jiǎn)單工廠模式雖然簡(jiǎn)單冕香,并且實(shí)現(xiàn)了創(chuàng)建和使用分離的功能蛹尝,但存在一個(gè)很嚴(yán)重的問(wèn)題。當(dāng)系統(tǒng)中需要引入...
    666真666閱讀 275評(píng)論 0 1
  • 設(shè)計(jì)模式匯總 一悉尾、基礎(chǔ)知識(shí) 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用突那、多...
    MinoyJet閱讀 3,948評(píng)論 1 15
  • 【韓喜文2018.09.04星期二】 好展館讓天下沒(méi)有賣不出去的產(chǎn)品 好展館讓天下沒(méi)有不能傳承的文化 日精進(jìn):95...
    韓喜文閱讀 121評(píng)論 0 0