抽象工廠模式的實質是提供「介面」,子類通過實現這些介面來定義具體的操作。
這些通用的介面如同協議一樣,協議本身定義了一系列方法去描述某個類,子類通過實現這些方法從而實現了該類。
子類中不用關心這個類該是什麼樣子的,這些都有抽象類去定義,這就區分設計類和實現類兩個過程,實現過程的解耦。
程式碼描述
描述一個這樣的過程:有一個 GUIFactory,GUI 有 Mac 和 Windows 兩種風格,現在需要建立兩種不同風格的 Button,顯示在 Application 中。
class GUIFactory(object):
def __init__(self):
self.screen = None
def set_screen(self):
raise NotImplementedError
def get_size_from_screen(self, screen):
if self.screen == 'retina':
return '2560 x 1600'
elif self.screen == 'full_hd':
return '1920 x 1080'複製程式碼
定義 Mac 和 Windows 兩種風格的 GUI。
class MacGUIFactory(GUIFactory):
def __init__(self):
super(MacGUIFactory, self).__init__()
def set_screen(self):
self.screen = 'retina'
def set_attributes(*args, **kwargs):
raise NotImplementedError
class WinGUIFactory(GUIFactory):
def __init__(self):
super(WinGUIFactory, self).__init__()
def set_screen(self):
self.screen = 'full_hd'
def set_attributes(*args, **kwargs):
raise NotImplementedError複製程式碼
所有 GUI 都需要設定螢幕的型別,否則在呼叫時候會丟擲 NotImplementedError
的異常,抽象了設定 Button 屬性的方法,讓子類必須實現。
class MacButton(MacGUIFactory):
def __init__(self):
super(MacButton, self).__init__()
self.set_screen()
self.color = 'black'
def set_attributes(self, *args, **kwargs):
if 'color' in kwargs:
self.color = kwargs.get('color')
def verbose(self):
size = self.get_size_from_screen(self.screen)
print('''i am the {color} button of mac on {size} screen'''.format(
color=self.color, size=size))
class WinButton(WinGUIFactory):
def __init__(self):
super(WinButton, self).__init__()
self.set_screen()
self.color = 'black'
def set_attributes(self, *args, **kwargs):
if 'color' in kwargs:
self.color = kwargs.get('color')
def verbose(self):
size = self.get_size_from_screen(self.screen)
print('''i am the {color} button of win on {size} screen'''.format(
color=self.color, size=size))複製程式碼
實現建立不同平臺 Button 的方法, 需要根據螢幕的大小建立不同尺寸的 Button,才能有更好的顯示效果。
這樣就分別實現了兩種不同 Button 的建立,還可以封裝一個 Button 類來管理這兩個不同的 Button。
class Button(object):
@staticmethod
def create(platform, *args, **kwargs):
if platform.lower() == 'mac':
return MacButton()
elif platform.lower() == 'win':
return WinButton()複製程式碼
建立兩個不同平臺的 Button,並且設定顏色屬性
win_button = Button.create('win')
mac_button = Button.create('mac')
win_button.set_attributes(color='red')
mac_button.set_attributes(color='blue')
win_button.verbose()
# >> i am the red button of win on 1920 x 1080 screen
mac_button.verbose()
# >> i am the blue button of mac on 2560 x 1600 screen複製程式碼
適用範圍
以下情況可以適用抽象工廠模式:
- 獨立於系統的模組
- 系統中各大類的模組
- 需要強調設計和實現分離的時候
- 只想顯示介面並不想實現的時候
優缺點
優點:
- 具體產品從客戶程式碼中被分離出來
- 容易改變產品的系列
- 將一個系列的產品族統一到一起建立
缺點:
- 在產品族中擴充套件新的產品是很困難的,它需要修改抽象工廠的介面