摘要:源碼參考抽象工廠模式抽象工廠模式提供一個接口,用于創建相關或依賴對象的家族,而不需要指定具體類。工廠方法模式和抽象工廠模式如何選擇開始的時候,可以選擇工廠方法模式,因為他很簡單只需要繼承,并實現工廠方法即可。
問題:在上一篇 python設計模式:工廠方法模式我們嘗試使用工廠方法創建了披薩店,現在為了保證披薩加盟店也能有良好的聲譽,我們需要統一原材料,這個該如何做呢?
為了確保每家加盟店都是用高質量的原材料,我們打算建造一加原材料工廠,并將原材料運送到各個加盟店。每個加盟店會對原材料有不同的需求,這里我們就可以用上上一篇介紹的工廠方法模式了。
首先,建造原料工廠
然后建造區域的原料工廠(繼承自原料工廠)
在區域的原料工廠中實現原料的創建方法。
將原料工廠組合起來,加入到 PizzaStore(上一篇中由工廠方法實現)代碼中。
按照這個思路,我們先創建原料工廠
創建原料工廠創建原料工廠的實現代碼如下:
# 原料 class FreshClams: def __str__(self): return "Fresh Clams" class MarinaraSauce: def __str__(self): return "Marinara Sauce" class ThickCrustDough: def __str__(self): return "Thick Crust Dough" class ReggianoCheese: def __str__(self): return "Reggiano Cheese" class SlicedPepperoni: def __str__(self): return "Sliced Pepperoni" class Garlic: def __str__(self): return "Garlic" class Onion: def __str__(self): return "Onion" class RedPepper: def __str__(self): return "Red Pepper" # 披薩店原料工廠 class PizzaIngredientFactory: """ 定義原料工廠 """ def create_dough(self): raise NotImplementedError() def create_sauce(self): raise NotImplementedError() def create_cheese(self): raise NotImplementedError() def create_pepperoni(self): raise NotImplementedError() def create_clam(self): raise NotImplementedError() def create_veggies(self): raise NotImplementedError()
在這個工廠中,每個原料都是一個方法,原料的實現需要在具體的原料工廠中實現。
這里每個原料方法沒有做任何工作,只是拋出了NotImplementedError 這樣做是為了強制子類重新實現相應的方法,如果不重新實現用到時就會拋出 NotImplementedError。
創建紐約原料工廠當然也可以把 PizzaIngredientFactory 的 metaclass 設置成 abc.ABCMeta 這樣的話,這個類就是真正的抽象基類。
class NYPizzaIngredientFactory(PizzaIngredientFactory): def create_dough(self): print("Tossing %s" % ThickCrustDough()) return ThickCrustDough() def create_sauce(self): print("Adding %s..." % MarinaraSauce()) return MarinaraSauce() def create_cheese(self): print("Adding %s..." % ReggianoCheese()) return ReggianoCheese() def create_pepperoni(self): print("Adding %s..." % SlicedPepperoni()) return SlicedPepperoni() def create_clam(self): print("Adding %s..." % FreshClams()) return FreshClams() def create_veggies(self): # 蔬菜可能有多種,這里使用列表 veggies = [Garlic(), Onion(), RedPepper()] for veggie in veggies: print(" %s" % veggie) return veggies
對于原料家族的每一種原料,我們都提供了原料的紐約版本。
重做 Pizza 類class Pizza: name = None dough = None sauce = None cheese = None veggies = [] pepperoni = None clam = None def prepare(self): raise NotImplementedError() def bake(self): print("Bake for 25 minutes at 350") def cut(self): print("Cutting the pizza into diagonal slices") def box(self): print("Place pizza in official PizzaStore box") def __str__(self): return self.name
上述代碼和工廠方法的代碼相比,只是把 prepare() 方法抽象出來,需要相應的 具體的 pizza 類來實現 prepare()。
實現 芝加哥芝士披薩class NYStyleCheesePizza(Pizza): def prepare(self): dough = self.ingredient_factory.create_dough() sauce = self.ingredient_factory.create_sauce() cheese = self.ingredient_factory.create_cheese() clam = self.ingredient_factory.create_clam() veggies = self.ingredient_factory.create_veggies()
從上述代碼可以發現,Pizza 的原料也是從原料工廠直接獲取,現在我們控制了原料。
重新實現 PizzaStore現在,Pizza 類不需要關心原料,只需要負責制作 pizza 就好。Pizza 和原料被解耦。
class PizzaStore: # 需要聲明原料工廠 ingredient_factory = None def create_pizza(self, pizza_type): # 每個需要子類實現的方法都會拋出NotImplementedError # 我們也可以把 PizzaStore 的 metaclass 設置成 abc.ABCMeta # 這樣的話,這個類就是真正的抽象基類 raise NotImplementedError() def order_pizza(self, pizza_type): # 現在把 pizza 的類型傳入 order_pizza() pizza = self.create_pizza(pizza_type) # 一旦我們有了一個 pizza,需要做一些準備(搟面皮、加佐料),然后烘烤、切片、裝盒 pizza.prepare() pizza.bake() pizza.cut() pizza.box() return pizza class NYStylePizzStore(PizzaStore): # 將需要用到的原料工廠賦值給變量 ingredient_factory ingredient_factory = NYPizzaIngredientFactory() def create_pizza(self, pizza_type): # 根據 pizza 類型,我們實例化正確的具體類,然后將其賦值給 pizza 實例變量 if pizza_type == "cheese": pizza = NYStyleCheesePizza("NY Style Sauce and Cheese Pizza", self.ingredient_factory) elif pizza_type == "clam": pizza = NYStyleClamPizza("NY Style Clam Pizza", self.ingredient_factory) return pizza
通過上述代碼可以看到我們做了以下工作:
引入了新類型的工廠(抽象工廠)來創建原料家族
通過抽象工廠提供的接口,我們創建了原料家族。
我們的原料代碼從實際的 Pizza 工廠中成功解耦,可以應用到不同地方,響應的,我們可以方便的替換原料工廠來生產不同的 pizza。
來看下下單的代碼def main(): nystore = NYStylePizzStore() pizza = nystore.order_pizza("cheese") print("*" * 10) print("goodspeed ordered a %s" % pizza) print("*" * 10)
和工廠方法的代碼相比,沒有任何改變。
[源碼參考python-design-patter-abstract-factory.py](https://gist.github.com/gusibi/5e0797f5458678322486f999ca87a180)
抽象工廠模式抽象工廠模式提供一個接口,用于創建相關或依賴對象的家族,而不需要指定具體類。
也就是說,抽象工廠允許客戶使用抽象的接口來創建一組相關的產品,而不需要知道實際產出的具體產品是什么,這樣依賴,客戶就從具體產品中被解耦。
概括來說就是,抽象工廠是邏輯上的一組工廠方法,每個工廠方法各司其職,負責生產不同種類的對象。
我們來看下 抽象工廠模式 的類圖:
抽象工廠在 django_factory 中應用比較多,有興趣的可以看下源碼。
抽象工廠模式 和 工廠方法模式 的比較抽象工廠模式 和 工廠方法模式 都是負責創建對象,但
工廠方法模式使用的是繼承
抽象工廠模式使用的是對象的組合
這也就意味著利用工廠方法創建對象需要擴展一個類,并覆蓋它的工廠方法(負責將客戶從具體類中解耦)。
抽象工廠提供一個用來創建產品家族的抽象類型,這個類型的子類定義了產品被產生的方法。要想使用這個工廠(NYPizzaIngredientFactory),必須先實例化它(ingredient_factory = NYPizzaIngredientFactory()),然后將它傳入一些針對抽象類型所寫的代碼中(也做到了將客戶從具體產品中解耦),同時還把一群相關的產品集合起來。
開始的時候,可以選擇工廠方法模式,因為他很簡單(只需要繼承,并實現工廠方法即可)。如果后來發現應用需要用到多個工廠方法,那么是時候使用抽象工廠模式了,它可以把相關的工廠方法組合起來。
抽象工廠模式優點和缺點 優點可以將客戶從具體產品中解耦
抽象工廠可以讓對象創建更容易被追蹤
同時將對象創建與使用解耦
也可以優化內存占用提升應用性能
缺點因為抽象工廠是將一組相關的產品集合起來,如果需要擴展這組產品,就需要改變接口,而改變接口則意味著需要改變每個子類的接口
參考鏈接python設計模式:工廠方法模式
python-design-patter-abstract-factory.py https://gist.github.com/gusibi/5e0797f5458678322486f999ca87a180
最后,感謝女朋友支持。
歡迎關注(April_Louisa) | 請我喝芬達 |
---|---|
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/40974.html
摘要:所謂的產品族,一般或多或少的都存在一定的關聯,抽象工廠模式就可以在類內部對產品族的關聯關系進行定義和描述,而不必專門引入一個新的類來進行管理。 0x01.定義與類型 定義:抽象工廠模式提供一個創建一系列相關或相互依賴對象的接口 無需指定它們具體的類 類型:創建型 UML showImg(https://segmentfault.com/img/bVbtBp1?w=800&h=862...
摘要:本文會用實現三種工廠模式的簡單例子,所有代碼都托管在上。工廠方法模式繼承了簡單工廠模式的優點又有所改進,其不再通過一個工廠類來負責所有產品的創建,而是將具體創建工作交給相應的子類去做,這使得工廠方法模式可以允許系統能夠更高效的擴展。 前言 工廠模式,顧名思義就是我們可以通過一個指定的工廠獲得需要的產品,在設計模式中主要用于抽象對象的創建過程,讓用戶可以指定自己想要的對象而不必關心對象的...
摘要:工廠方法模式可以幫助我們將產品的實現從使用中解耦。應用中使用工廠模式的例子的模塊使用工廠方法模式來創建表單字段。也使用到了工廠方法模式。中不同數據庫連接部分也用到了工廠方法模式。 題目:假設你有一個 pizza 店,功能包括下訂單、做 pizza,你的代碼會如何寫呢? def order_pizza(): pizza = Pizza() pizza.prepare() ...
摘要:通過工廠方法模式的類圖可以看到,工廠方法模式有四個要素工廠接口工廠接口是工廠方法模式的核心,與調用者直接交互用來提供產品。使用場景創建類模式,在任何需要生成復雜對象的地方,都可以使用工廠方法模式。 0x01.定義與類型 定義:定義一個創建對象的接口,但讓實現這個接口的類來決定實例化那個類,工廠方法讓類的實例化推遲到子類中進行 類型:創建型 uml類圖 showImg(https:/...
摘要:在工廠方法模式中,我們會遇到一個問題,當產品非常多時,繼續使用工廠方法模式會產生非常多的工廠類。從簡單工廠模式到抽象工廠模式,我們都是在用后一種模式解決前一種模式的缺陷,都是在最大程度降低代碼的耦合性。 單例模式 所謂單例模式,也就是說不管什么時候我們要確保只有一個對象實例存在。很多情況下,整個系統中只需要存在一個對象,所有的信息都從這個對象獲取,比如系統的配置對象,或者是線程池。這些...
閱讀 2950·2021-11-23 09:51
閱讀 3776·2021-11-22 15:29
閱讀 3226·2021-10-08 10:05
閱讀 1552·2021-09-22 15:20
閱讀 952·2019-08-30 15:56
閱讀 1069·2019-08-30 15:54
閱讀 733·2019-08-26 11:54
閱讀 2636·2019-08-26 11:32