造房子時(shí)需要一個(gè)門杨名,你是穿上木匠服開始在你家門口鋸木頭,搞得一團(tuán)糟猖毫?還是從工廠里生產(chǎn)一個(gè)台谍?
依賴倒置原則,指導(dǎo)我們避免依賴具體類型吁断,而要盡量依賴抽象趁蕊。所有的工廠都是用來封裝對(duì)象的創(chuàng)建,以便將代碼從具體類解耦仔役。
我們把三個(gè)工廠理一遍:
- 簡(jiǎn)單工廠掷伙,是針對(duì)一種“類型”的抽象。
- 工廠方法又兵,是針對(duì)一種“類型”任柜,以及一種“創(chuàng)建方法”的抽象。
- 抽象工廠沛厨,是針對(duì)一組“類型”與“創(chuàng)建方法”的抽象宙地,組內(nèi)每一套類型與創(chuàng)建方法一一對(duì)應(yīng)。
用造門這個(gè)例子來說:
- 簡(jiǎn)單工廠逆皮,是封裝了“造門”的操作宅粥,輸出的是一種門。
- 工廠方法电谣,是封裝了“多種造門”的操作秽梅,并委托“多家工廠”,輸出的是“各種門”剿牺。
- 抽象工廠企垦,是封裝了“多種造門”的操作,“提供多種專業(yè)人員”的操作晒来,并委托給“多家工廠”钞诡,輸出的是“各種門”,以及“各種專業(yè)人員”,且“門”與“專業(yè)人員”一一對(duì)應(yīng)臭增。
附客戶端調(diào)用的代碼:
$door = DoorFactory::makeDoor(100, 200); // 客戶不需要先指定委托對(duì)象懂酱。傳遞門寬高,輸出一種規(guī)格的門
// 木門
$woodenDoorManager = new WoodenDoorManager();
$door = $woodenDoorManager->makeDoor(100, 200);
// 鐵門
$ironDoorManager = new IronDoorManager();
$door = $ironDoorManager->makeDoor(100, 200); // 客戶需要先指定委托對(duì)象誊抛。委托給*DoorManager列牺,輸出"各種門"
// 木門
$woodenFactory = new WoodenDoorFactory();
$door = $woodenFactory->makeDoor(); // 輸出門
$expert = $woodenFactory->makeFittingExpert(); // 還輸出專業(yè)人員,且"門"與"專業(yè)人員"一一對(duì)應(yīng)拗窃。
$door->getDescription();
$expert->getDescription();
// 鐵門
$ironFactory = new IronDoorFactory();
$door = $ironFactory->makeDoor();
$expert = $ironFactory->makeFittingExpert();
$door->getDescription();
$expert->getDescription(); // 多種造門瞎领。委托給"多家工廠",輸出"各種門"随夸。且"門"與"專業(yè)人員"一一對(duì)應(yīng)九默。
附分別的UML圖:
定義一個(gè)工廠類,它可以根據(jù)參數(shù)的不同返回不同類的實(shí)例宾毒,被創(chuàng)建的實(shí)例通常都具有共同的父類驼修。
定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類決定將哪一個(gè)類實(shí)例化诈铛。工廠方法模式讓一個(gè)類的實(shí)例化延遲到其子類乙各。
提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口,而無須指定它們具體的類幢竹。
工廠方法和簡(jiǎn)單工廠有啥區(qū)別耳峦?
兩者最大的區(qū)別:抽象的維度。
- 簡(jiǎn)單工廠的抽象焕毫,是一維的蹲坷,它抽象的僅僅是所創(chuàng)建"類型"的接口;
- 而工廠方法的抽象邑飒,是二維的循签,它不僅抽象了所創(chuàng)建"類型"的接口,而且抽象了"方法"的接口幸乒。
具體到例子里懦底,簡(jiǎn)單工廠實(shí)例中,客戶就是要一個(gè)門, 而不關(guān)心創(chuàng)建過程, 最后實(shí)際創(chuàng)造的是一個(gè)木門罕扎。這個(gè)頗為諷刺,如果客戶要的是個(gè)鐵門呢丐重?那就事與愿違了腔召。
所以在這個(gè)例子里, 也是存在兩維抽象的。一是"門"這個(gè)類型的抽象扮惦,二是"造門"這個(gè)方法的抽象臀蛛。簡(jiǎn)單工廠只做到了前者,而沒有給出后者的解決方案,這才造成了客戶可能吃了啞巴虧浊仆。
如果我們按照工廠方法的思路客峭,將門工廠造門這件事進(jìn)行細(xì)分,木門交給木門工廠抡柿,鐵門交給鐵門工廠舔琅。這就和工廠方法里的例子別無二致了≈蘖樱客戶需要先指定委托對(duì)象备蚓,而不關(guān)心具體怎么造門。
簡(jiǎn)單工廠和抽象工廠有啥區(qū)別囱稽?
依然可以用維度來理解抽象工廠郊尝。 抽象工廠比工廠方法又多了一維。
例子中战惊,抽象工廠提供了兩套“類型 - 創(chuàng)建操作”(分別是"門 - 造門"流昏,"專業(yè)人員 - 提供專業(yè)人員"),其實(shí)這個(gè)個(gè)數(shù)是無限的吞获。
你可以提供 n 套這樣的對(duì)應(yīng)關(guān)系况凉,然后委托給相關(guān)的工廠。這就是“工廠們的工廠”的具體含義衫哥。