from abc importabcmeta,abstractmethod
class coke(metaclass=abcmeta):
@abstractmethod
defdrink(self):
pass
class
coca(coke):
defdrink(self):
print('
drink coca-cola')
class
pepsi(coke):
defdrink(self):
print('
drink pepsi-cola')
class
fast_food_restaurant():
defmake_coke(self ,name):
return
eval(name)()
kcd=fast_food_restaurant()
coke=kcd.make_coke('
coca')
coke.drink()
#drink coca-cola
abcmeta是python的乙個元類,用於在python程式中建立抽象基類,抽象基類中宣告的抽象方法,使用abstractmethod裝飾器裝飾。
eval(類名)返回的是乙個class型別的物件。
舉個例子可以更加明確的理解。我們建立乙個可樂的抽象類,百事可樂和可口可樂繼承這個抽象類,我們又建立了快餐店類,也就是所說的工廠類,讓它生產可樂。當使用者需要可樂時,只需要告訴快餐店做乙份什麼品牌的可樂,告訴快餐店可樂的名字,然後快餐店使用make_coke方法做可樂,返回了你所需要的物件——一杯可口可樂,然後就可以快樂的喝可樂了。。
簡單工廠模式已經幫我們做到我們需要某種物件時,可以不關心物件是怎麼建立的,只需要向工廠類要物件即可,但是如果我們又多了一種物件,例如又出現了乙個可樂品牌,嗯,我們叫它sfencs可樂吧,那麼我們快餐店也得新新增這種可樂,也就是工廠類也得能夠建立sfencs可樂物件了,但是這樣就得在工廠類中加入新的邏輯判斷來根據使用者需求製造新新增的這個物件,顯然是不恰當的,因為這樣每當有乙個新的型別的可樂增加的時候,我們都得修改工廠類的邏輯**,使之能夠判斷出新的型別。這個問題使用工廠方法模式可以得到解決。
這裡有乙個小問題,如上面的簡單工廠模式的**,如果要新加sfencs可樂,似乎並不需要修改快餐店工廠類,只需要在sfencs可樂類定義之後,依然向make_coke函式傳遞類名即可,那這樣豈不是不需要工廠方法模式了嗎?
對於這個現象,其實是得益於eval()函式的功能,它能依據傳入的字串轉換成相應的類,也就是eval函式就是工廠類的邏輯判斷,如果不使用eval,那麼邏輯判斷可能就是多個if語句了,判斷條件就是輸入的字串引數是否等於這個,是否等於那個。。。等。但是eval使用也有很大的侷限性,它只能根據字串來判斷,我們不一定建立物件時都知道它的類名。除此之外,個人感覺eval這個函式有點厲害,越厲害就有可能造成不必要的麻煩,eval使用時還是得多注意。
from abc importabcmeta,abstractmethod
class coke(metaclass=abcmeta):
@abstractmethod
defdrink(self):
pass
class
coca(coke):
defdrink(self):
print('
drink coca-cola')
class
pepsi(coke):
defdrink(self):
print('
drink pepsi-cola')
class
sfencs(coke):
defdrink(self):
print('
drink sfencs-cola')
class fast_food_restaurant(metaclass=abcmeta):
@abstractmethod
defmake_coke(self):
pass
class
coca_produce(fast_food_restaurant):
defmake_coke(self):
return
coca()
class
pepsi_produce(fast_food_restaurant):
defmake_coke(self):
return
pepsi()
class
sfencs_produce(fast_food_restaurant):
defmake_coke(self):
return
sfencs()
kcd=sfencs_produce()
coke=kcd.make_coke()
coke.drink()
#drink sfencs-cola
工廠方法模式將原來的工廠類變為了抽象類,不同型別的可樂通過不同的子類生產,也就是工廠方法模式定義了乙個建立物件的介面,但具體建立哪個類的物件由子類來決定,這種方式的邏輯判斷相當於交給了客戶端,也就是kcd=sfencs_produce()來選擇使用哪個子類,這樣如果有新可樂產品出現的話,只需要再寫乙個子類繼承工廠抽象類。
這裡的類中,快餐店抽象類也叫做抽象工廠類,它的子類稱為具體工廠類。可樂也一樣,coke為抽象產品類,它的子類為具體產品類。
抽象工廠模式的主要目的是提供乙個介面來建立一系列相關物件而無需指定具體的類。這個模式與與工廠方法模式的區別在於,它的乙個方法子類,可以建立一系列的物件。
依然用可樂來舉例,只喝普通的可樂還不足以讓我們非常快樂,那麼如果有一杯冰可樂,想必就能滿足我們了。
於是我們的抽象產品類變為了兩個,乙個是冰可樂,乙個是普通可樂,具體產品類有百事冰可樂、可口可樂冰可樂,普通百事,普通可口可樂。抽象工廠類有生產冰可樂和生產普通可樂的抽象方法,具體工廠類有百事工廠,可口可樂工廠。
from abc importabcmeta,abstractmethod
class ice_coke(metaclass=abcmeta):
@abstractmethod
defdrink(self):
pass
class ordinary_coke(metaclass=abcmeta):
@abstractmethod
defdrink(self):
pass
class
coca_ice(ice_coke):
defdrink(self):
print('
drink coca-ice-cola')
class
pepsi_ice(ice_coke):
defdrink(self):
print('
drink pepsi-ice-cola')
class
coca_ordinary(ordinary_coke):
defdrink(self):
print('
drink coca-ordinary-cola')
class
pepsi_ordinary(ordinary_coke):
defdrink(self):
print('
drink pepsi-ordinary-cola')
class fast_food_restaurant(metaclass=abcmeta):
@abstractmethod
defmake_ice_coke(self):
pass
@abstractmethod
defmake_ordinary_coke(self):
pass
class
coca_produce(fast_food_restaurant):
defmake_ice_coke(self):
return
coca_ice()
defmake_ordinary_coke(self):
return
coca_ordinary()
class
pepsi_produce(fast_food_restaurant):
defmake_ice_coke(self):
return
pepsi_ice()
defmake_ordinary_coke(self):
return
pepsi_ordinary()
kcd=coca_produce()
coke=kcd.make_ice_coke()
coke.drink()
#drink coca-ice-cola
Python設計模式之工廠模式
工廠模式,可以理解為建立乙個工廠 類 這個工廠會根據你的需求 輸入 生產出 輸出 你想要的產品 物件 簡單說就是工廠類會根據你的輸入給你返回恰當的物件。class shape staticmethod deffactory shape if shape square return square if...
python學習 設計模式之 工廠模式
一 工廠模式運用場景 若需要將物件的建立和使用解耦,工廠方法也能派上用場。工廠方法可以在必要時建立新的物件,從而提高效能和記憶體使用率。二 工廠模式案例 import xml.etree.elementtree as etree import json class jsonconnector def...
設計模式 設計模式之工廠模式
工廠方法模式 建立模式 使用場景?作用?形態?場景 大量類似的實體類 要建立的實體類都是同一本質的東西 披薩 有部分類似功能 準備 烘烤 切法 實現方式不一樣 準備的材料不同 烘烤時間不同 切法不同 將繁瑣複雜的建立類的過程聚集在一起,有序清晰 把具體例項化的過程從客戶 中抽離 作用 1 將建立物件...