《設計模式》涉及到創建類的幾種模式,共同的也是最根本的原則就是:不要new對象!!!既然如此,告訴我你最先想到的是如何得到對象呢?沒錯,“你不讓我new,那你給我個get對象的工具吧,別的我不管”。這就是工廠模式,工廠模式是一種簡單又實用的模式,在各大框架到處可見,比如Java世界大名鼎鼎的spring,其本身就是一個大工廠。
工廠模式中,工廠的作用是解耦調用者和被調用者的關係,工廠模式又分爲工廠方法模式和簡單工廠模式。我們先說工廠方法模式,下面舉個現實的栗子。
比如說一個鞋廠,生產皮鞋和球鞋,安利公司打電話來說給我一批皮鞋,恆大足球隊打電話說來給我一批球鞋,鞋廠很開心的按時交付了。我們用代碼來模擬這個場景,鞋廠就是抽象工廠,其下兩個車間--皮鞋車間和球鞋車間--是具體的工廠,皮鞋和球鞋都是產品,安利和恆大是客戶端。下面是實現代碼:
# 鞋,基類(抽象產品類)
class Shoe:
def walk(self):
pass
# 皮鞋(具體產品)
class LeatherShoe(Shoe):
def walk(self):
print("優雅的皮鞋,去拉客戶中")
# 球鞋(具體產品)
class SoccerShoe(Shoe):
def walk(self):
print("憤怒的球鞋,正在蹂躪草坪")
# 鞋廠,基類(抽象工廠)
class ShoeFactory:
def make_shoe(self):
pass
# 皮鞋車間(具體工廠)
class LeatherShoeFactory(ShoeFactory):
def make_shoe(self):
return LeatherShoe()
# 球鞋車間(具體工廠)
class SoccerShoeFactory(ShoeFactory):
def make_shoe(self):
return SoccerShoe()
# 安利打電話要鞋
def anli_call():
factory = LeatherShoeFactory()
for i in range(3):
shoe = factory.make_shoe()
shoe.walk()
# 恆大打電話要鞋
def hengda_call():
factory = SoccerShoeFactory()
for i in range(3):
shoe = factory.make_shoe()
shoe.walk()
if __name__ == '__main__':
anli_call()
hengda_call()
這裏模擬安利和恆大分別下單購了3雙鞋,運行結果如下:
優雅的皮鞋,去拉客戶中
優雅的皮鞋,去拉客戶中
優雅的皮鞋,去拉客戶中
憤怒的球鞋,正在蹂躪草坪
憤怒的球鞋,正在蹂躪草坪
憤怒的球鞋,正在蹂躪草坪
上面例子中的每個具體工廠都只生產一種產品,假設該鞋廠很牛逼,一個車間什麼鞋都能生產。我們去掉兩個子工廠,把父工廠改爲這樣:# 鞋廠,基類(抽象工廠)
class ShoeFactory:
def make_shoe(self, name):
if name == "LeatherShoe":
return LeatherShoe()
elif name == "SoccerShoe":
return SoccerShoe()
else:
return None
客戶方法要改爲如下:# 安利打電話要鞋
def anli_call():
factory = ShoeFactory()
for i in range(3):
shoe = factory.make_shoe("LeatherShoe")
shoe.walk()
# 恆大打電話要鞋
def hengda_call():
factory = ShoeFactory()
for i in range(3):
shoe = factory.make_shoe("SoccerShoe")
shoe.walk()
運行結果和上面一下,這種被稱爲簡單工廠模式。簡單工廠模式相對工廠方法模式代碼複雜度有所降低,但是每次增加產品,就要修改工廠類,擴展性差。
讀者應該會納悶了,這什麼玩意,整這麼複雜,我幾行代碼循環new幾個對象完事兒。是的,例子中這種簡單的實體對象是不需要工廠模式的,用它來舉例是因爲它很能體現“工廠”的概念。說實話本人真正在項目中沒有用到工廠模式,都只是在框架裏見到它的出現,比如spring對bean對管理、json序列化生成單例類等。感覺只有在寫框架的時候才需要它,業務代碼多是行爲類,以策略模式居多,不過話說到此,是不是可以用工廠模式管理行爲類呢?回頭我嘗試一下。
下面是我的一點感受:
工廠與產品之間是一種弱聯繫,將上面例子中的球鞋車間改爲生產皮鞋,完全不會有任何問題,所以工廠模式需要良好的命名約定。再加上python是弱語言類型,又沒有抽象的概念,很難約束子類,這樣在設計工廠的時候務必保持類名清晰,使調用者一眼就知道能得到什麼產品。