簡單工廠模式、工廠模式和抽象工廠模式區別及優缺點
- 2019 年 10 月 25 日
- 筆記
各位小夥伴好,今天給大家主要介紹一下簡單工廠模式、工廠模式和抽象工廠模式的區別及各自的優缺點。
(本文實現語言為Python3)
【前言】
眾所周知今天所講的內容是設計模式的一類;對於設計模式這個概念,我想首先請大家問問自己:1、什麼是設計模式 2、我們為什麼要了解並學習設計模式?
從我上學的時候我相信大家跟我一樣也接觸過設計模式的課程,當時可能懵懵懂懂只是知其然,當時還會想明明可以直接寫出來為什麼要搞成這樣的形式,我就算學會了它到底什麼時候能用呢?一系列的問題…Emm算了到時候再想想(lazy)。隨著實踐的不斷增多,現在我想可以對這些問題有個初步的回答了:
1、在我看來,設計模式外在看是經過前人不斷實踐總結出的針對某些指定場景極其好用的一種程式碼結構設計模板;內在看其實是一種設計思想(即為什麼他們會這麼想,這樣想較之其他方法有什麼好處)。當我們真正的理解設計思想的時候,就可能會在面對問題和場景時自然而然的靈活運用到多種設計模式,而不是單一的刻板結構。
2、在工程化的開發中,需求往往是會不斷變化的,這也是讓很多開發人員及其煩躁的地方,所以才會有開發與產品的親密關係。設計模式就是為了抵禦外部需求變化產生的。設計模式應符合開閉原則(類、模組和函數等應該對擴展開放,對修改關閉。)一個好的設計在之後的開發中,包括發生重大需求變化的時候,往往程式碼只需要進行簡單重構去進行適配,而不是通過打修補程式的方式去堆砌,也很容易避免破窗效應,充分的發揮了靈活的擴展和適配,大大增強了維護性。
綜上所述,我們了解並學習設計模式,可以使我們的程式碼變得更加健壯、結構清晰,可以從容、靈活的適配需求變更(可復用、可擴展、可維護、夠靈活)
【正文】
首先,這三種模式解決的問題是實例化對象的問題;那麼為什麼不直接實例化而用這樣的工廠形式去實例化對象呢?
因為【待實例化對象太多(子類多且變動、調用頻繁)或者實例化對象的過程、準備比較複雜】,直接實例化意味著每次都用重複的去執行實例化這個操作,如果有很多待實例化的操作,那麼就要重複執行很多次,更不要說萬一在實例化之前還要執行一堆配置項的初始化。所以用工廠模式去代替直接實例化對象是為了可復用,並且可以實現模組間的解耦。
如果是簡單的實例化是沒有必要引入工廠模式的,這樣還會增加系統的複雜度。
簡單工廠模式和抽象工廠模式都是派生於工廠模式的,屬於一類;在對問題的解決上你可以理解成三種方案,解決某類問題用某種方案最好;但在複雜程度上來說算是層層遞進的。我這裡就按實現的簡單程度升序說明。(這裡我準備用實例化手機對象舉例說明)
一、簡單工廠模式(又叫靜態工廠模式)
顧名思義,這是對工廠模式的一種“簡單”實現,也是理解起來比較簡單的。它的本質是通過傳入不同的參數來實現多態,達到實例化不同對象的目的。
class MobileFactory: """ 簡單工廠模式 生產手機的工廠""" def get_mobile(self, name): if name == 'huawei': return HuaWei() elif name == 'iphone': return Iphone() class MobliePhone: pass class HuaWei(MobliePhone): pass class Iphone(MobliePhone): pass hw = MobileFactory().get_mobile('huawei') ip = MobileFactory().get_mobile('iphone') print(hw) # <__main__.HuaWei object at 0x00000000021F9160> print(ip) # <__main__.Iphone object at 0x00000000022AD0F0>
二、工廠模式(又稱為創建模式)
是對簡單工廠模式多了一層抽象,將實例化某一類對象具體細分給對應的工廠,而不是在一個工廠里通過依賴參數
class MobileFactory: """ 工廠模式 生產手機的工廠""" def get_mobile(self): pass class HWFactory(MobileFactory): def get_mobile(self): return 'get a HW phone' class IphoneFactory(MobileFactory): def get_mobile(self): return 'get an iphone' hw, ip = HWFactory(), IphoneFactory() print(hw.get_mobile()) # get a HW phone print(ip.get_mobile()) # get an iphone
三、抽象工廠模式
是對工廠模式又進行了一層抽象,不單單是像工廠模式只生成一類產品,而是一系列產品,並且可以像零件一樣靈活配置給各工廠。
""" 抽象工廠模式 【假設】華為和蘋果都生產手機和螢幕,而我家只生產螢幕 """ # 有螢幕和手機兩款產品 class Screen: def __init__(self): print('i am a screen') class Mobile: def __init__(self): print('i am a mobile') # 三個廠家各自的螢幕和手機 class HWScreen(Screen): def __init__(self): print('HW screen') class IphoneScreen(Screen): def __init__(self): print('Iphone screen') class MyScreen(Screen): def __init__(self): print('My screen') class HWMobile(Mobile): def __init__(self): print('HW Mobile') class IphoneMobile(Mobile): def __init__(self): print('Iphone Mobile') # 生產工廠 class Factory: def get_screen(self): pass def get_mobile(self): pass # 各家自己的工廠 class HWFactory(Factory): def get_mobile(self): return HWMobile() def get_screen(self): return HWScreen() class IphoneFactory(Factory): def get_screen(self): return IphoneScreen() def get_mobile(self): return IphoneMobile() class MyFactory(Factory): def get_screen(self): return MyScreen() # 我要生產東西咯 hw, ip, my = HWFactory(), IphoneFactory(), MyFactory() hw.get_mobile() # HW Mobile hw.get_screen() # HW screen ip.get_mobile() # Iphone Mobile ip.get_screen() # Iphone screen my.get_screen() # My screen
【總結與說明】
首先說明由於Python面向對象比較徹底,天然的實現了多態,所以例子看起來可能不如靜態語言Java更加清晰,但是可以通過例子理解要傳遞表達的設計思想。
看完上述三段程式碼示例後,相信大家可能有的人會豁然開朗,有的人可能只是剛剛梳理好思路。在這裡我希望大家先問問自己三個模式的優缺點,並且帶著對它們的疑問進行程式碼實踐,這樣才會對理解和感悟有更深刻的認識。
一、簡單工廠模式 【優點】:1、客戶端創建對象時只需要記住特定的參數,而不需要記住複雜的類名,也不用關注實現的過程。(實現了封裝和部分解耦)
2、創建對象不需要單獨實例化,而是通過工廠類直接獲取示例(實現復用)
【缺點】:1、實例化對象的邏輯全部封裝在一個工廠類里,每次需求變化都要單獨修改工廠類(違反了開閉原則),而且出了異常可能沒法正常工作。
2、不方便擴展子類
【應用場景】:適合業務簡單或者產品較少的情況
二、工廠模式 【優點】:1、在簡單工廠的基礎上遵循了開閉原則,又進行了解耦,工廠類分為具體的工廠類
【缺點】:1、每增加一個工廠,就要額外開發一個工廠
【應用場景】:正文中符合工廠模式的情況,多由於解耦
三、抽象工廠模式 【優點】:1、正是由於複雜的抽象關聯關係使得在類的內部對一系列產品組的管理很方便
【缺點】:1、擴展很費力,每次要修改很多類。
【應用場景】:待創建的對象是一系列相互關聯或相互依賴的產品族時