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