设计模式之工厂模式(三)
上一次我們已經(jīng)通過(guò)代碼,簡(jiǎn)單的認(rèn)識(shí)了工廠方法模式,具體的思路請(qǐng)移步到設(shè)計(jì)模式之工廠模式(二),進(jìn)行查看。這次,讓我們通過(guò)設(shè)計(jì)模式的思想,來(lái)好好認(rèn)識(shí)下工廠方法模式。
創(chuàng)建者和產(chǎn)品
所有工廠模式都用來(lái)封裝對(duì)象的創(chuàng)建。工廠方法模式(Factory Method Pattern)通過(guò)讓子類(lèi)決定該創(chuàng)建的對(duì)象是什么,來(lái)達(dá)到將對(duì)象創(chuàng)建的過(guò)程封裝的目的。讓我們來(lái)看看這些類(lèi)圖,以了解有哪些組成元素:
另一個(gè)觀點(diǎn):平行的類(lèi)層級(jí)
上面已經(jīng)看到,將一個(gè)orderPizza()方法和一個(gè)工廠方法聯(lián)合起來(lái),就可以成為一個(gè)框架。除此之外,工廠方法將生產(chǎn)知識(shí)封裝進(jìn)各個(gè)創(chuàng)建者,這樣的做法,也可以被視為是一個(gè)框架。
讓我們來(lái)看看這兩個(gè)平行的類(lèi)層級(jí),并認(rèn)清它們的關(guān)系:
定義工廠方法模式
工廠方法模式定義了一個(gè)創(chuàng)建對(duì)象的接口,但由子類(lèi)決定要實(shí)例化的類(lèi)是哪一個(gè)。工廠方法讓類(lèi)把實(shí)例化推遲到子類(lèi)。
工廠方法模式能夠封裝具體類(lèi)型的實(shí)例化。看下面的類(lèi)圖,抽象的Creator提供了一個(gè)創(chuàng)建對(duì)象的方法的接口,也稱(chēng)為“工廠方法”。在抽象的Creator中,任何其他實(shí)現(xiàn)的方法,都可能使用到這個(gè)工廠方法所制造出來(lái)的產(chǎn)品,但只有子類(lèi)真正實(shí)現(xiàn)這個(gè)工廠方法并創(chuàng)建產(chǎn)品。
對(duì)象依賴(lài)
假設(shè)你從未聽(tīng)過(guò)工廠模式,那么按照之前的,如果要開(kāi)一家紐約和芝加哥的披薩店,并且有各種風(fēng)味的披薩對(duì)象,你是否可以想象這個(gè)類(lèi)所以來(lái)的具體披薩對(duì)象有幾種呢?如果又增加了一種加州風(fēng)味,又會(huì)有依賴(lài)多少個(gè)對(duì)象呢?不妨讓你看看:
public lass DependentPizzaStore {public Pizza createPizza(String style, String type) {Pizza pizza = null;if(style.equals("NY")) {if(type.equals("cheese")) {pizza = new NYStyleCheesePizza();} else if(tpye.equals("clam")) {pizza = new NYStyleClamPizza();} else if(type.equals("pepperoni")) {pizza = new NYStylePrpperoniPizza();}} else if(style.equals("Chicago")) {if(type.equals("cheese")) {pizza = new ChicagoStyleCheesePizza();} else if(tpye.equals("clam")) {pizza = new ChicagoStyleClamPizza();} else if(type.equals("pepperoni")) {pizza = new ChicagoStylePrpperoniPizza();}} else {System.out.println("Error: invalid type of pizza");return null;}} } 復(fù)制代碼當(dāng)你直接實(shí)例化一個(gè)對(duì)象時(shí),就是在依賴(lài)它的具體類(lèi)。如果把這個(gè)版本的披薩店和它的依賴(lài)對(duì)象畫(huà)成一張畫(huà),看起來(lái)是這樣的:
依賴(lài)倒置原則
從上面看到了,我們代碼里減少對(duì)于具體類(lèi)的依賴(lài)是一件好事。事實(shí)上,有一個(gè)OO設(shè)計(jì)原則就正式闡明了這一點(diǎn);這個(gè)原則甚至還有一個(gè)又響亮又正式的名稱(chēng):“依賴(lài)倒置原則”。要依賴(lài)抽象,不要依賴(lài)具體類(lèi)。
這個(gè)原則和“針對(duì)接口編程,不針對(duì)實(shí)現(xiàn)編程”類(lèi)似,但是這個(gè)原則,更強(qiáng)調(diào)“抽象”。這個(gè)原則說(shuō)明了:不能讓高層組件依賴(lài)低層組件,而且,不管高層或低層組件,“兩者”都應(yīng)該依賴(lài)于抽象。
所謂“高層”組件, 是是由其他低層組件定義行為的類(lèi)。例如,PizzaStore是個(gè)高層組件,因?yàn)樗男袨槭怯膳_定義的;PizzaStore創(chuàng)建所有不同的披薩對(duì)象,準(zhǔn)備、烘烤、切片、裝盒;而披薩本身屬于低層組件。PizzaStore依賴(lài)這些具體披薩類(lèi)。
原則的應(yīng)用
非常依賴(lài)披薩店的主要問(wèn)題在于:它依賴(lài)每個(gè)披薩類(lèi)型。因?yàn)樗窃谧约旱膐rderPizza()方法中,實(shí)例化這些具體類(lèi)型的。
如何在orderPizza()方法中,將這些實(shí)例化對(duì)象的代碼獨(dú)立出來(lái)?我們都知道,工廠方法剛好派上用場(chǎng)了。應(yīng)用了工廠方法之后,類(lèi)圖就改成了下面這個(gè)樣子:
在應(yīng)用工廠方法之后,你注意到了沒(méi),高層組件(PizzaStore)和低層組件(也就是這些披薩)都依賴(lài)了Pizza抽象。想要遵循依賴(lài)倒置原則,工廠方法并非是唯一的技巧,但卻是最有威力的技巧之一了。
依賴(lài)倒置,究竟倒置在哪里?
在依賴(lài)倒置原則中的倒置指的是和一般OO設(shè)計(jì)的思考方式相反。看看上面的圖,你會(huì)注意到低層組件現(xiàn)在竟然依賴(lài)高層的抽象。同樣地,高層組件現(xiàn)在也依賴(lài)相同的抽象。以前繪制的依賴(lài)圖都是自上而下的,現(xiàn)在卻倒置了,而且高層和低層模塊現(xiàn)在都依賴(lài)這個(gè)抽象。
依賴(lài)倒置,還需要倒置你的思考方式。之前如果你需要設(shè)計(jì)一個(gè)披薩店,會(huì)從頂端開(kāi)始,然后往下到具體類(lèi)。現(xiàn)在就需要倒置你的想法,別從頂端開(kāi)始,而是從披薩開(kāi)始,然后想到抽象化一個(gè)Pizza類(lèi)。繼而想到必須要靠一個(gè)工廠來(lái)將這些類(lèi)取出披薩店,不同的披薩類(lèi)型都只能依賴(lài)一個(gè)抽象,同樣的披薩店也會(huì)依賴(lài)這個(gè)抽象。
就這樣,我們倒置了一個(gè)商店依賴(lài)具體類(lèi)的設(shè)計(jì),而且也倒置了你的思考方式。但是,也需要避免在OO設(shè)計(jì)中違反依賴(lài)倒置原則:
所以,這篇我們就在這里結(jié)束了。為什么呢,因?yàn)樵谙乱黄?#xff0c;我們需要遵循這個(gè)設(shè)計(jì)原則,重新來(lái)整理整理我們的披薩店。我們要讓披薩店的設(shè)計(jì)變得更棒:具有彈性的框架,而且遵循設(shè)計(jì)原則。這篇偏向理論知識(shí)了,請(qǐng)各位好好理解理解,看看創(chuàng)建者和產(chǎn)品類(lèi),看看依賴(lài)倒置原則,我們下篇再見(jiàn)咯。
愛(ài)生活,愛(ài)學(xué)習(xí),愛(ài)感悟,愛(ài)挨踢轉(zhuǎn)載于:https://juejin.im/post/5cbd42956fb9a032060c2615
總結(jié)
以上是生活随笔為你收集整理的设计模式之工厂模式(三)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 图解 Java 线程的生命周期,看完再也
- 下一篇: jsp页面模块的来源