摘要:假設(shè)需要?jiǎng)?chuàng)建一個(gè)矩形,我們可以這樣做需要一個(gè)圓形也簡(jiǎn)單實(shí)際上,我們通常是在界面上,一般是工具欄上,放置兩個(gè)按鈕,讓用戶選擇哪個(gè)按鈕,然后創(chuàng)建此形狀。
作為創(chuàng)建型設(shè)計(jì)模式,帶有工廠名字的設(shè)計(jì)模式共有三個(gè),分別是
Simple Factory
Factory Method
Abstract Factory
其中的 Simple Factory并不是GoF一書中的模式,但是它是最基礎(chǔ)最常用的,并且也是循序漸進(jìn)的了解另外兩個(gè)工廠的必要基礎(chǔ),所有放在一起講它們是比較科學(xué)的。
三者常常是容易搞混的,我就見過若干個(gè)搞混的案例。要么,比起這更難的,是不太容易弄明白使用的場(chǎng)景和目的。本文試圖通過一個(gè)案例,講清楚三者的內(nèi)涵,但是不準(zhǔn)備講解它的外延。
假設(shè)我們想要做一個(gè)圖形編輯器,我們把它的需求壓低到極為簡(jiǎn)潔的形式,只要和當(dāng)前要描述的問題無(wú)關(guān)的,我們都不會(huì)引入:
可以創(chuàng)建兩種形狀,矩形和圓形
可以設(shè)置形狀的顏色,紅色和黃色
那么,系統(tǒng)中必然需要如下的Shape類:
class Shape{draw(){}} class Rect extends Shape{draw(){}} class Circle extends Shape{draw(){}}
以及,系統(tǒng)中必然需要如下的Color類:
class Color{fill(){}} class Red extends Color{fill(){}} class Yellow extends Color{fill(){}}
我們首先從Shape開始。假設(shè)需要?jiǎng)?chuàng)建一個(gè)矩形,我們可以這樣做:
var rect = new Rect()
需要一個(gè)圓形也簡(jiǎn)單:
var rect = new Circle()
實(shí)際上,我們通常是在界面上,一般是工具欄上,放置兩個(gè)按鈕,讓用戶選擇哪個(gè)按鈕,然后創(chuàng)建此形狀。用戶選擇了矩形,接下來創(chuàng)建就是矩形,選擇的是圓形,那么創(chuàng)建就是圓形。所以這樣的代碼一定是存在的:
if (userSelected = "rect") return new Rect() if (userSelected = "circle") return new Circle()Simple Factory
Simple Factory的價(jià)值就是讓調(diào)用者從創(chuàng)建邏輯中解脫,只要傳遞一個(gè)參數(shù),就可以獲得創(chuàng)建對(duì)象。實(shí)際上,從對(duì)象職責(zé)來說,這段代碼不應(yīng)該是Rect或者是Circle的,也不應(yīng)該是UI類的,UI類在不同的應(yīng)用中是不一樣的,但是我們知道作為頂層類,需要負(fù)責(zé)UI顯示和事件,不應(yīng)該負(fù)責(zé)創(chuàng)建對(duì)象的邏輯。實(shí)際上,很多代碼放到此處,特別容易導(dǎo)致代碼擁擠,主控類職責(zé)過多的問題。
最好引入一個(gè)新的類,像是這樣:
class ShapeCREATEOR{ create(userSelected){ if (userSelected = "rect") return new Rect() if (userSelected = "circle") return new Circle() } }
這個(gè)類的所有邏輯,都是專門用于創(chuàng)建其他類。因?yàn)榉浅3R?,人們?yōu)樗∶麨镕actory,其他被創(chuàng)建的類被稱為Product。所以慣例上來說,此類的名字會(huì)冠以工廠名:
class ShapeFactory
根據(jù)傳入的參數(shù),決定創(chuàng)建哪一個(gè)產(chǎn)品類,此類就被稱為簡(jiǎn)單工廠類(Simple Factory)。有了工廠類,使用者就可以直接使用工廠類獲得需要的對(duì)象:
var sf = new ShapeFactory() var rect = sf.create("rect")
于是,所有需要?jiǎng)?chuàng)建矩形的場(chǎng)合,你知道,一個(gè)UI App,除了工具欄,還有菜單,都只要寫這樣的代碼就可以創(chuàng)建了。而不必到處根據(jù)userSelected來做分支了。這就是使用工廠的好處。如果支持命令創(chuàng)建,甚至使用json文件中恢復(fù)對(duì)象時(shí),本來也需要傳遞字符串來決定創(chuàng)建對(duì)象時(shí),就顯得簡(jiǎn)單工廠的好處了。
factory method簡(jiǎn)單工廠根據(jù)傳入的參數(shù)決定實(shí)例化哪一個(gè)類,而factory method有子類來決定實(shí)例化哪一個(gè)類。
class Shape{draw(){}} class Rect extends Shape{draw(){}} class Circle extends Shape{draw(){}} class ShapeFactory{ createShape(){} } class RectFactory extends ShapeFactory{ createShape(){return new Rect()} } class CircleFactory extends ShapeFactory{ createShape(){return new Circle()} }
調(diào)用者需要?jiǎng)?chuàng)建Rect,只要這樣:
var f = new RectFactory() f.createShape()
這是factory method的定義:
創(chuàng)建一個(gè)接口,但是由子類決定實(shí)例化哪一個(gè)類
這里提到的接口是ShapeFactory.createShape,提到的子類為:RectFactory,CircleFactory。這樣做就意味著,在工廠內(nèi)不必根據(jù)傳入?yún)?shù)分支,它作為子類本身就知道要?jiǎng)?chuàng)建的是哪一個(gè)產(chǎn)品。使用對(duì)應(yīng)的工廠,創(chuàng)建需要的類。
AbstractFactory要是我們創(chuàng)建的類型不僅僅是Shape,還有Color的話,AbstractFactory就有價(jià)值。AbstractFactory提供一個(gè)接口a,此接口可以創(chuàng)建一系列相關(guān)或者相互依賴的對(duì)象b,使用用戶不需要指定具體的類即可創(chuàng)建它們c。
我們先看代碼:
class Shape{draw(){}} class Rect extends Shape{draw(){}} class Circle extends Shape{draw(){}} class ShapeFactory{ createShape(type){ if (shape == "rect"){ return new Rect() }else{ return new Circle() } } } class Color{fill(){}} class Red extends Color{fill(){}} class Yellow extends Color{fill(){}} class ColorFactory { creatColor(type){ if (shape == "Red"){ return new Red() }else if (shape == "Yellow"{ return new Yellow() } } }
如果希望客戶可以一個(gè)單一接口來訪問Color和Shape,可以引入一個(gè)抽象工廠:
class AbstractFactory{ createShape(){} createColor(){} }
要求兩個(gè)工廠實(shí)現(xiàn)此抽象工廠:
class ShapeFactory extends AbstractFactory{ createShape(type){ if (shape == "rect"){ return new Rect() }else{ return new Circle() } } createColor(){ return null } } class ColorFactory extends AbstractFactory{ createShape(type){return null} creatColor(type){ if (shape == "Red"){ return new Red() }else if (shape == "Yellow"{ return new Yellow() } } }
自己不具備的能力,不實(shí)現(xiàn)即可,這里就是返回一個(gè)null。需要一個(gè)創(chuàng)建工程的簡(jiǎn)單工廠
class FactoryProducer{ getFactory(type){ if (type == "color")return new ColorFactory() else return new ShapeFactory() } }
沒有抽象工廠,那么代碼是這樣的,所有的Factory類的創(chuàng)建都是硬編碼的
var sf = new ShapeFactory() var r = sf.createColor("Rect") r.draw() var cf = new ColorFactory() var c = cf.createColor("Red") c.fill()
有了抽象工廠,那么客戶的使用就是這樣
var fp = new FactoryProducer() var sf = fp.getFactory("shape") var r = sf.createColor("Rect") r.draw() var cf = fp.getFactory("color") var c = cf.createColor("Red") c.fill()
好處是,硬編碼創(chuàng)建的類只有一個(gè),就是FactoryProducer。
其中難懂的部分,做一個(gè)進(jìn)一步說明:
接口a:AbstractFactory內(nèi)的兩個(gè)函數(shù)createShape,createColor
一系列相關(guān)或者相互依賴的對(duì)象b: Shape系列類,Color系列類
使用用戶不需要指定具體的類即可創(chuàng)建它們c:實(shí)際上,用戶只要使用FactoryProducer這一個(gè)類,不需要使用任何一個(gè)工廠,以及工廠創(chuàng)建的類。
本文host于 https://github.com/1000copy/d... ,歡迎folk。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/92086.html
摘要:使用的好處知乎的回答不用自己組裝,拿來就用。統(tǒng)一配置,便于修改。 前言 只有光頭才能變強(qiáng) 回顧前面: 給女朋友講解什么是代理模式 包裝模式就是這么簡(jiǎn)單啦 單例模式你會(huì)幾種寫法? 工廠模式理解了沒有? 在刷Spring書籍的時(shí)候花了點(diǎn)時(shí)間去學(xué)習(xí)了單例模式和工廠模式,總的來說還是非常值得的! 本來想的是刷完《Spring 實(shí)戰(zhàn) (第4版)》和《精通Spring4.x 企業(yè)應(yīng)用開發(fā)實(shí)戰(zhàn)》...
摘要:文章目錄一云聚惠一云聚惠二星星海云服務(wù)器二星星海云服務(wù)器三企業(yè)用戶福利專場(chǎng)三企業(yè)用戶福利專場(chǎng)騰訊云怎么樣騰訊云是騰訊公司旗下的云計(jì)算服務(wù)品牌,國(guó)內(nèi)知名企業(yè),云服務(wù)器產(chǎn)品自然穩(wěn)定靠譜,是個(gè)人企業(yè)的最佳選擇,適合建站小程序項(xiàng)目游戲服務(wù) 文章目錄一、618云聚惠二、星星海云服務(wù)器三、企業(yè)用戶福利專場(chǎng)騰訊云怎么樣?騰訊云是騰訊公司旗下的云計(jì)算服務(wù)品牌,國(guó)內(nèi)知名IT企業(yè),云服務(wù)器產(chǎn)品自然穩(wěn)定...
摘要:那有什么辦法保證只有一個(gè)領(lǐng)導(dǎo)人斯大林呢較常見的兩種方式餓漢式和懶漢式二實(shí)戰(zhàn)圖這里提示一點(diǎn),在學(xué)習(xí)設(shè)計(jì)模式的時(shí)候,圖會(huì)讓你更容易,而且深刻的去理解到該模式的核心。下一篇的設(shè)計(jì)模式是工廠方法模式。 ??就算不懂設(shè)計(jì)模式的兄弟姐妹們,想必也聽說過單例模式,并且在項(xiàng)目中也會(huì)用上。但是,真正理解和熟悉單例模式的人有幾個(gè)呢?接下來我們一起來學(xué)習(xí)設(shè)計(jì)模式中最簡(jiǎn)單的模式之一——單例模式 一、為什么叫單...
閱讀 2013·2021-11-15 18:09
閱讀 908·2021-09-06 15:13
閱讀 2646·2021-08-23 09:43
閱讀 2030·2019-08-30 15:54
閱讀 2225·2019-08-30 13:56
閱讀 2489·2019-08-26 11:31
閱讀 3088·2019-08-26 10:56
閱讀 711·2019-08-26 10:28