摘要:本文會用實現三種工廠模式的簡單例子,所有代碼都托管在上。工廠方法模式繼承了簡單工廠模式的優點又有所改進,其不再通過一個工廠類來負責所有產品的創建,而是將具體創建工作交給相應的子類去做,這使得工廠方法模式可以允許系統能夠更高效的擴展。
前言
工廠模式,顧名思義就是我們可以通過一個指定的“工廠”獲得需要的“產品”,在設計模式中主要用于抽象對象的創建過程,讓用戶可以指定自己想要的對象而不必關心對象的實例化過程。這樣做的好處是用戶只需通過固定的接口而不是直接去調用類的實例化方法來獲得一個對象的實例,隱藏了實例創建過程的復雜度,解耦了生產實例和使用實例的代碼,降低了維護的復雜性。
本文會用Python實現三種工廠模式的簡單例子,所有代碼都托管在Github上。
首先,我們先看一個簡單工廠的例子:
#coding=utf-8 class Mercedes(object): """梅賽德斯 """ def __repr__(self): return "Mercedes-Benz" class BMW(object): """寶馬 """ def __repr__(self): return "BMW"
假設我們有兩個“產品”分別是Mercedes和BMW的汽車,如果沒有“工廠”來生產它們,我們就要在代碼中自己進行實例化,如:
mercedes = Mercedes() bmw = BMW()
但現實中,你可能會面對很多汽車產品,而且每個產品的構造參數還不一樣,這樣在創建實例時會遇到麻煩。這時就可以構造一個“簡單工廠”把所有汽車實例化的過程封裝在里面。
class SimpleCarFactory(object): """簡單工廠 """ @staticmethod def product_car(name): if name == "mb": return Mercedes() elif name == "bmw": return BMW()
有了SimpleCarFactory類后,就可以通過向固定的接口傳入參數獲得想要的對象實例,如下:
c1 = SimpleCarFactory.product_car("mb") c2 = SimpleCarFactory.product_car("bmw")工廠方法
雖然有了一個簡單的工廠,但在實際使用工廠的過程中,我們會發現新問題:如果我們要新增一個“產品”,例如Audi的汽車,我們除了新增一個Audi類外還要修改SimpleCarFactory內的product_car方法。這樣就違背了軟件設計中的開閉原則[1],即在擴展新的類時,盡量不要修改原有代碼。所以我們在簡單工廠的基礎上把SimpleCarFactory抽象成不同的工廠,每個工廠對應生成自己的產品,這就是工廠方法。
#coding=utf-8 import abc class AbstractFactory(object): """抽象工廠 """ __metaclass__ = abc.ABCMeta @abc.abstractmethod def product_car(self): pass class MercedesFactory(AbstractFactory): """梅賽德斯工廠 """ def product_car(self): return Mercedes() class BMWFactory(AbstractFactory): """寶馬工廠 """ def product_car(self): return BMW()
我們把工廠抽象出來用abc模塊[2]實現了一個抽象的基類AbstractFactory,這樣就可以通過特定的工廠來獲得特定的產品實例了:
c1 = MercedesFactory().product_car() c2 = BMWFactory().product_car()
每個工廠負責生產自己的產品也避免了我們在新增產品時需要修改工廠的代碼,而只要增加相應的工廠即可。如新增一個Audi產品,只需新增一個Audi類和AudiFactory類。
抽象工廠工廠方法雖然解決了我們“修改代碼”的問題,但如果我們要生產很多產品,就會發現我們同樣需要寫很多對應的工廠類。比如如果MercedesFactory和BMWFactory不僅生產小汽車,還要生產SUV,那我們用工廠方法就要再多構造兩個生產SUV的工廠類。所以為了解決這個問題,我們就要再更進一步的抽象工廠類,讓一個工廠可以生產同一類的多個產品,這就是抽象工廠。具體實現如下:
#coding=utf-8 import abc # 兩種小汽車 class Mercedes_C63(object): """梅賽德斯 C63 """ def __repr__(self): return "Mercedes-Benz: C63" class BMW_M3(object): """寶馬 M3 """ def __repr__(self): return "BMW: M3" # 兩種SUV class Mercedes_G63(object): """梅賽德斯 G63 """ def __repr__(self): return "Mercedes-Benz: G63" class BMW_X5(object): """寶馬 X5 """ def __repr__(self): return "BMW: X5" class AbstractFactory(object): """抽象工廠 可以生產小汽車外,還可以生產SUV """ __metaclass__ = abc.ABCMeta @abc.abstractmethod def product_car(self): pass @abc.abstractmethod def product_suv(self): pass class MercedesFactory(AbstractFactory): """梅賽德斯工廠 """ def product_car(self): return Mercedes_C63() def product_suv(self): return Mercedes_G63() class BMWFactory(AbstractFactory): """寶馬工廠 """ def product_car(self): return BMW_M3() def product_suv(self): return BMW_X5()
我們讓基類AbstractFactory同時可以生產汽車和SUV,然后令MercedesFactory和BMWFactory繼承AbstractFactory并重寫product_car和product_suv方法即可。
c1 = MercedesFactory().product_car() s1 = MercedesFactory().product_suv() print(c1, s1) s2 = BMWFactory().product_suv() c2 = BMWFactory().product_car() print(c2, s2)
抽象工廠模式與工廠方法模式最大的區別在于,抽象工廠中的一個工廠對象可以負責多個不同產品對象的創建 ,這樣比工廠方法模式更為簡單、有效率。
結論初學設計模式時會對三種工廠模式的實際應用比較困惑,其實三種模式各有優缺點,應用的場景也不盡相同:
簡單工廠模式適用于需創建的對象較少,不會造成工廠方法中的業務邏輯太過復雜的情況下,而且用戶只關心那種類型的實例被創建,并不關心其初始化過程時,比如多種數據庫(MySQL/MongoDB)的實例,多種格式文件的解析器(XML/JSON)等。
工廠方法模式繼承了簡單工廠模式的優點又有所改進,其不再通過一個工廠類來負責所有產品的創建,而是將具體創建工作交給相應的子類去做,這使得工廠方法模式可以允許系統能夠更高效的擴展。實際應用中可以用來實現系統的日志系統等,比如具體的程序運行日志,網絡日志,數據庫日志等都可以用具體的工廠類來創建。
抽象工廠模式在工廠方法基礎上擴展了工廠對多個產品創建的支持,更適合一些大型系統,比如系統中有多于一個的產品族,且這些產品族類的產品需實現同樣的接口,像很多軟件系統界面中不同主題下不同的按鈕、文本框、字體等等。
參考[1]維基百科
[2]Python官方文檔
2018/1/30更新:修改工廠方法的代碼示例,新增結論一節。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/41319.html
摘要:源碼參考抽象工廠模式抽象工廠模式提供一個接口,用于創建相關或依賴對象的家族,而不需要指定具體類。工廠方法模式和抽象工廠模式如何選擇開始的時候,可以選擇工廠方法模式,因為他很簡單只需要繼承,并實現工廠方法即可。 問題:在上一篇 python設計模式:工廠方法模式我們嘗試使用工廠方法創建了披薩店,現在為了保證披薩加盟店也能有良好的聲譽,我們需要統一原材料,這個該如何做呢? 為了確保每家加盟...
摘要:通過工廠方法模式的類圖可以看到,工廠方法模式有四個要素工廠接口工廠接口是工廠方法模式的核心,與調用者直接交互用來提供產品。使用場景創建類模式,在任何需要生成復雜對象的地方,都可以使用工廠方法模式。 0x01.定義與類型 定義:定義一個創建對象的接口,但讓實現這個接口的類來決定實例化那個類,工廠方法讓類的實例化推遲到子類中進行 類型:創建型 uml類圖 showImg(https:/...
摘要:類型創建型,但不屬于中設計模式。簡介通過一個專門的工廠類來創建其他類,這些被創建的類通常有一個共同的父類或接口。相關代碼簡單工廠模式推薦閱讀慕課網設計模式精講簡單工廠模式 0x01.定義與類型 定義:由一個工廠對象決定創建出哪一種產品類的實例。 類型:創建型,但不屬于GOF23中設計模式。 簡介:通過一個專門的工廠類來創建其他類,這些被創建的類通常有一個共同的父類或接口。 uml類圖...
摘要:工廠方法模式可以幫助我們將產品的實現從使用中解耦。應用中使用工廠模式的例子的模塊使用工廠方法模式來創建表單字段。也使用到了工廠方法模式。中不同數據庫連接部分也用到了工廠方法模式。 題目:假設你有一個 pizza 店,功能包括下訂單、做 pizza,你的代碼會如何寫呢? def order_pizza(): pizza = Pizza() pizza.prepare() ...
摘要:在工廠方法模式中,我們會遇到一個問題,當產品非常多時,繼續使用工廠方法模式會產生非常多的工廠類。從簡單工廠模式到抽象工廠模式,我們都是在用后一種模式解決前一種模式的缺陷,都是在最大程度降低代碼的耦合性。 單例模式 所謂單例模式,也就是說不管什么時候我們要確保只有一個對象實例存在。很多情況下,整個系統中只需要存在一個對象,所有的信息都從這個對象獲取,比如系統的配置對象,或者是線程池。這些...
閱讀 2978·2023-04-25 19:45
閱讀 2695·2021-11-19 09:40
閱讀 701·2021-10-14 09:49
閱讀 2702·2021-09-30 09:47
閱讀 2230·2021-09-26 09:55
閱讀 1231·2021-09-22 16:01
閱讀 2817·2019-08-30 14:19
閱讀 711·2019-08-29 16:44