歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> 更多Linux

Python設計模式——Abstract Factory模式

  一、簡介  抽象工廠(Abstract Factory)模式又稱為Kit模式,屬於對象創建型模式,它擁有比簡單工廠模式和工廠方法模式更高的抽象性,是所有工廠模式中最為抽象和最具一般性的形態。抽象工廠模式是一種重要的架構型組件(Architectural Component),它負責提供統一的接口,用來生成一簇"相互關聯"或者"相互依賴"的多態對象(Polymorphic Object)。     考慮一個具有多種風格(Theme)的GUI工具包,它能夠同時支持KDE和GNOME等類型的桌面環境,不同的桌面風格負責為諸如按鈕、文本框和滾動條這樣的窗口控件(Widget)定義不同的外觀和行為。很顯然,應用程序不應該針對某種特定的桌面風格硬編碼它的窗口控件,否則之後如果需要使用另外一種桌面風格就必須對源代碼進行修改,或者換句話說,在應用程序中實例化特定桌面風格的窗口控件將使得今後很難再對應用程序的桌面風格進行更改。解決的辦法是首先定義一個抽象的WidgetFactory類,它負責聲明用於創建每一類窗口控件的公共接口,然後再為每一類窗口控件定義一個共同的抽象父類,並且使用與之對應的具體子類來實現特定風格的窗口控件。對於每一個抽象的窗口控件類,WidgetFactory都提供一個返回相應對象的方法,這樣應用程序就可以通過調用這些方法來獲得窗口控件的實例,而不用關心當前正在使用的是哪些具體類,從而也就可以不再依賴於某種具體的桌面風格了,整個GUI工具包的系統結構如圖1所示。     圖1  每一種桌面風格都對應於WidgetFactory的一個具體子類,它們負責實現在WidgetFactory中定義的用來創建相應窗口控件的方法。例如,調用KDEWidgetFactory中的createButton()方法可以創建一個KDE桌面環境下的按鈕,而調用GNOMEWidgetFactory中的createButton()方法則可以創建一個GNOME桌面環境下的按鈕。此處的WidgetFactory就是一個抽象工廠,它使得應用程序只需通過在WidgetFactory中定義的接口就可以得到相應的窗口控件,而不用關心整個GUI軟件包中究竟是哪些類實現了特定風格的窗口控件。運用抽象工廠模式的好處是客戶端可以完全獨立於產品的創建過程,只要與抽象工廠類中定義的公共接口進行交互就可以了,而無需對具體的產品類進行實例化操作。     抽象工廠模式與工廠方法模式最大的區別在於:工廠方法模式針對的是一個產品等級結構,而抽象工廠模式則針對的是多個產品等級結構。正因如此,在抽象工廠模式中經常會用到產品族(ProdUCt Family)這一概念,它指的是位於不同的產品等級結構中,並且功能相互關聯的產品系列。圖2中箭頭所指的就是三個功能相互關聯的產品,它們位於三個不同的產品等級結構中的相同位置上,共同組成了一個產品族。     圖2  不難看出,如果使用抽象工廠模式,那麼僅需要一個工廠等級結構就可以創建出分屬於不同產品等級結構的產品族中的所有對象,因此抽象工廠模式同工廠方法模式相比效率更高。抽象工廠這一模式適合在如下場合中運用:     當軟件系統要求獨立於產品的創建、組合和表示的時候,其實這對任何形態的工廠模式來講這都是很重要的。   當軟件系統要由多個產品族中的一個來進行配置的時候,此時系統中會存在多於一個的產品族,但同一時刻只會消費其中某一族的產品,這是抽象工廠模式的原始用意。   當一簇相關產品被設計成應該被組合使用的時候,即同屬於某個產品族的多個產品是需要在一起配套使用的,這一約束必須在系統設計時體現出來。   當需要提供一個產品庫,並且只想暴露接口而不是實現的時候,這樣所有的產品都能夠以同樣的接口出現,從而使得客戶端可以不依賴於具體的實現。   二、模式引入  抽象工廠模式的一個主要功能是它能夠隔離要生成的具體產品類,由於這些類的實際類名都被隱藏在工廠裡面,因此客戶端根本不需要關心如何對它們進行實例化的細節。每一種設計模式都是針對特定問題的解決方案,而抽象工廠模式面臨的問題則是當涉及到有多個產品等級結構時,如何更好地進行軟件體系結構的設計。下面從一個具體的問題出發,將抽象工廠模式引入到軟件系統的設計中來。     假設我們打算開發一個類似於Doom或者Quake那樣的格斗類游戲,為了適應不同等級玩家的需要,游戲特地安排了兩個難度級別:初等級別和高難級別。在初等級別中,敵方士兵反映遲鈍,怪獸步履緩慢,即便是初學者也能夠很輕松地取勝;但在高難級別中,敵方士兵反映敏捷,怪獸猙獰狡詐,就算是高級玩家也難逃被擊斃的厄運。     在具體實現時可以先設計兩個抽象產品類Soldier和Monster,用來代表士兵和怪獸,然後再分別從它們派生出SillySoldier和SillyMonster兩個具體產品類用於初等級別,以及WiseSoldier和WiseMonster兩個具體產品類用於高難級別。設計時一個值得注意的問題是,游戲在運行的過程中SillySoldier和WiseMonster是絕對不能同時出現的,因為玩家要麼就與SillySoldier和SillyMonster進行實戰演練,要麼就與WiseSoldier和WiseMonster展開艱苦的戰斗。不難看出,游戲在設計時依據難度級別形成了兩個產品族,玩家在游戲期間肯定會使用這兩個產品族中的某一族對象,但絕對不會同時使用它們。     為了保證這種一致性,程序員在編碼時必須非常小心,否則稍有疏忽,那些正在痛擊SillySoldier的游戲菜鳥們一轉身撞上一個WiseMonster,肯定會敗得一塌糊塗。抽象工廠模式可以很好地解決這一問題,在具體實現時可以先將游戲中所有Soldier和Monster對象的生成函數集中到一個抽象工廠AbstractEnemyFactory中,然後再根據不同的難度級別依次構造SillyEnemyFactory和WiseEnemyFactory兩個具體工廠,並由它們負責按照當前游戲策略的要求去生成具體的士兵和怪獸。這樣一來,整個游戲的體系結構就將如圖3所示。     圖3  AbstractEnemyFactory 是一個抽象工廠,它負責聲明被所有具體工廠所共有的構造性方法,其完整的代碼如清單1所示。在AbstractEnemyFactory中定義的createSoldier()和createMonster()是兩個抽象方法,它們必須在所有的具體工廠中給出相應的實現,這樣客戶端才有可能通過調用具體工廠中的這兩個方法,來獲得所需要的某種Soldier或者Monster對象。     代碼清單1:abstractenemyfactory.py  class AbstractEnemyFactory:   """ 負責創建Soldier和Monster的抽象工廠 """      # 創建Soldier的抽象方法   def createSoldier(self):  pass      # 創建Monster的抽象方法   def createMonster(self):  pass     SillyEnemyFactory 是 AbstractEnemyFactory 的一個具體實現,它負責實例化 SillySoldier 和 SillyMonster 對象,其完整的代碼如清單2所示。     代碼清單2:sillyenemyfactory.py  from sillysoldier import *  from sillymonster import *  from abstractenemyfactory import *    class SillyEnemyFactory(AbstractEnemyFactory):   """ 負責創建SillySoldier和SillyMonster的具體工廠 """      # 創建SillySoldier的具體方法   def createSoldier(self):  soldier = SillySoldier()  return soldier      # 創建SillyMonster的具體方法   def createMonster(self):  monster = SillyMonster()  return monster     WiseEnemyFactory 是 AbstractEnemyFactory 的另一個具體實現,它負責實例化 WiseSoldier 和 WiseMonster 對象,其完整的代碼如清單3所示。    代碼清單3:wiseenemyfactory.py  from wisesoldier import *  from wisemonster import *  from abstractenemyfactory import *    class WiseEnemyFactory(AbstractEnemyFactory):   """ 負責創建WiseSoldier和WiseMonster的具體工廠 """      # 創建WiseSoldier的具體方法   def createSoldier(self):  soldier = WiseSoldier()  return soldier      # 創建WiseMonster的具體方法   def createMonster(self):  monster = WiseMonster()  return monster     AbstractEnemyFactory 、 SillyEnemyFactory 和 WiseEnemyFactory 共同組成了抽象工廠模式中的工廠等級結構,其作用是為了更好地創建相應的 Soldier 和 Monster 產品對象。 Soldier 是游戲中所有士兵對象的抽象接口,其完整的代碼如清單4所示。     代碼清單4:soldier.py  class Soldier:   """ 所有士兵對象的抽象接口 """      # 獲取速度的抽象方法   def getSpeed(self):  pass      # 獲取武器的抽象方法   def getWeapon(self):  pass     SillySoldier 是 Soldier 的一個具體實現,它用來代表初等游戲級別中的士兵對象,其完整的代碼如清5所示。    代碼清單5:sillysoldier.py   from soldier import *    class SillySoldier(Soldier):   """ 初等級別中士兵對象的具體實現 """      # 構造函數   def __init__(self):  print "A SillySoldier is created."  self.speed = 10  self.weapon = "saber"




Copyright © Linux教程網 All Rights Reserved