python設計模式之門面模式


前面的單例模式及工廠模式都是屬於創建型設計模式,這裏要開始講結構型設計模式—門面模式。

這篇內容:
結構型設計模式概要
利用UML圖理解門面設計模式
門面模式與最少知識原則

理解結構型設計模式

結構型模式描述如何將對象和類組合成更大的結構
結構型模式是一種能夠簡化設計工作的模式,因爲它能夠找出更簡單的方法來認識或表示實體之間的關係。在面向對象世界中,結構型模式是一種能夠簡化設計工作的模式,因爲它能夠找出更簡單的方法來認識或表示實體之間的關係。在面向對象世界中,實體指的是對象或類。
類模式可以通過繼承來描述對象,從而提供更有用的程序接口,而對象模式則描述瞭如何將對象聯繫起來從而組成更大的對象,結構型模式是類和對象模式的綜合體。

 ##### 結構型設計模式例子:
  • 適配器模式:將一個接口轉換爲客戶希望的另外一個接口。它試圖根據客戶端的需求來匹配不同類的接口。
  • 橋接模式:該模式將對象的接口與其實現進行解耦,使得兩者可以獨立工作。
  • 裝飾器模式:該模式允許在運行時或以動態方式爲對象添加職責。我們可以通過接口給對象添加某些屬性。

理解門面設計模式

門面(facade)通常是指建築物的表面,尤其是最有吸引力的那一面。它也可以一種讓人容易誤解某人的真實感受或情況的行爲或面貌。當人們從建築物外面經過時,可以欣賞其外部面貌,卻不瞭解建築物結構的複雜性。這就是門面模式的使用方式。門面在隱藏內部系統複雜性的同時,爲客戶端提供了一個接口,以便它們可以非常輕鬆地訪問系統。
假設你要到某個商店買東西,但是你是第一次來到這個商店,你對這個商店的佈局並不瞭解。所以一般你都會找店主,因爲店主對這個店裏面的情況瞭如執掌。只要你告訴他你要買什麼,店主就會把這些商品拿給你。這不就變得簡單了嗎。顧客不必瞭解店面裏面佈局情況,可以通過一個簡單的接口(店主)來完成購物。

門面設計模式實際上完成了下列事項:

  • 它爲系統中的一組接口提供一個統一的接口,並定義一個高級接口來幫助客戶端通過更加簡單的方式使用子系統。

  • 門面解決的是,如何使用單個接口對象來表示複雜的子系統。實際上,它並不是封裝子系統,而是對底層子系統進行組合。

  • 它促進了實現與多個客戶端的解耦。

通過UML圖來深入探討門面模式:
在這裏插入圖片描述

就像你在UML圖所看這個模式有三個主要的參與者:

  1. 門面: 門面的主要責任是,將一組複雜導致系統封裝起來,從而爲外部世界提供一個舒適的外觀。
    系統:這代表一組不同的子系統,使整個系統混雜在一起,難以觀察或使用。
  2. 客戶端:客戶端與門面進行交互,這樣就可以輕鬆地與子系統進行通信並完成工作了。不必擔心繫統複雜性。

1.門面:

  1. 它是一個接口,它知道某個請求可以交由哪個子系統進行處理。
  2. 它使用組合將客戶端的請求委派給相應的子系統使用。

例如:如果客戶端正在瞭解哪些工作已完成,則不需要到各個子系統中去,相反它只需要聯繫完成工作的接口(門面)就可以了

2.系統:

  1. 它實現子系統的功能,同時,系統由一個類表示。理想的情況下系統應該由一組負責不同任務的類來表示。
  2. 它處理門面對象的分配的工作,但並不知道門面,而且不引用它。

例如,當客戶端向門面請求某項服務時,門面會根據服務的類型來選擇該服務的相應子系統。

3.客戶端

  1. 客戶端是實例化門面的類。
  2. 爲了讓子系統完成相應的工作,客戶端需要向門面提出請求。

現實世界中實現門面模式(示例)

假設你要在家中舉行一場婚禮,並且由你來張羅這一切。這真是一個艱鉅的任務。你必須預訂一家酒店或場地,與餐飲人員交代酒菜、佈置場景,並安排背景音樂。、
你已經自己搞定了一切,如找相關人員談話、與他們進行協調、敲定價格等,那麼現在你就很輕鬆了。此外,你還可以去找會務經理,讓他/她爲你處理這些事情。會務經理負責跟各個服務提供商交涉,併爲你爭取最優惠的價格。
下面我們從門面模式的角度來看待這些事情。
客戶端:你需要在婚禮前及時完成所有的準備工作。每一項安排都應該是頂級的,這樣客人才會喜歡這些慶祝活動。
門面:會務經理負責與所有相關人員進行交涉,這些人員負責處理食物、花卉裝飾等。
子系統:它們代表提供餐飲、酒店管理和花卉裝飾等服務的系統。

讓我們利用Python開發一個應用程序,實現這個示例。我們首先從客戶端開始。記住,你是確保婚姻準備工作和事件順利的總負責人!
下面是EventManager類的Python代碼:

class EventManager(object):
    """
    EventManager(活動經理)
    Hotelier(旅館經理)
    bookHotel(預定酒店)
    Florist(花商)
    setFlowerRequirements(花需求集)
    Caterer(承辦酒席的人)
    setCuisine(美食集)
    Musician(樂師)
    setMusicType(設置音樂類型)
    """
    def __init__(self):
        print('活動經理:讓我和大家談談\n')

    def arrange(self):
        self.hotelier = Hotelier()
        self.hotelier.bookHotel()
        self.florist = Florist()
        self.florist.setFlowerRequirements()
        self.caterer = Caterer()
        self.caterer.setCuisine()
        self.musician = Musician()
        self.musician.setMusicType()

這裏已經搞定了門面和客戶端,讓我們開始深入瞭解子系統。
所以開發了這個類:
Hotelier類用於預訂酒店。它有一個方法,用於檢查當天是否有免費的酒店(__isAvailable)
Florist類負責花卉裝飾。這個類提供了setFlowerRequirements()方法,用於指定要使用哪些種類的花卉來裝飾婚禮。
Caterer類用於跟備辦宴席者打交道,並負責安排餐飲。Caterer提供了一個公開的setCuisine()方法,用來指定婚宴的菜餚類型。
Musician類用來安排婚禮的音樂,它使用setMusicType(方法來了解會務的音樂要求。

接下來,先來考察Hotelier對象,其次是Florist對象及其方法。

class Hotelier(object):
    def __init__(self):
        print('爲婚禮安排酒店?--')

    def __isAvailable(self):
        print("在指定的日子裏,酒店是免費的嗎?")
        return True

    def bookHotel(self):
        if self.__isAvailable():
            print("註冊預訂\n\n")


class Florist(object):
    def __init__(self):
        print("爲活動做的花裝飾?--")

    def setFlowerRequirements(self):
        print("康乃馨、玫瑰和百合用來裝飾\n\n")


class Caterer(object):
    def __init__(self):
        print("活動的食物安排--")

    def setCuisine(self):
        print("中餐和西菜\n\n")


class Musician(object):
    def __init__(self):
        print("婚禮的音樂安排--")

    def setMusicType(self):
        print("將播放爵士樂和古典音樂\n\n")

是,我很聰明,所以將這些事情都委託給了會務經理,不是嗎? 讓我們來看看You類。在本示例中,創建了一個EventManager類的對象,這樣經理就會通過與相關人員進行交涉來籌備婚禮,而你則可以找個地方喝大茶了。

class You(object):
    def __init__(self):
        print("你:哇!婚姻的安排???!!!")

    def askEventManager(self):
        print("讓我們聯繫一下活動經理\n\n")
        em = EventManager()
        em.arrange()

    def __del__(self):
        print("感謝活動經理,所有的準備工作都完成了!唷!")

you = You()
you.askEventManager()

將門面模式和現實世界場景關聯起來。

EventManager類是簡化接口的門面。
EvementManager通過組合創建子系統的對象,如Hotelier,Caterer等等。

最少知識原則

  1. 門面爲我們提供了一個統一的系統。它使得子系統更加易於使用。它還將客戶端與子系統解耦。門面設計模式背後的設計原理就是最少知識原則。

  2. 最少知識原則指導我們減少對象之間的交互,就像你親近的只有某幾個朋友那樣。

  3. 在設計系統時,對於創建的每個對象,都應該考察與之交互的類的數量, 以及交互的方式。

  4. 遵循這個原則,就能夠避免創建許多彼此緊密耦合的類的情況。

  5. 如果類之間存在大量依賴關係,那麼系統就會變得難以維護。如果對系統中的任何一部分進行修改,都可能導致系統的其他部分被無意改變,這意味着系統會退化,這是應該堅決避免的。

迪米特法則(設計準則)

  1. 每個單元對系統中其他單元知道的越少越好。
  2. 單位應該只與其朋友交流。
  3. 單元不應該知道它操作的對象的內部細則。

說明: 最少知識原則和迪米特法則是一致的,都是指向松耦合理論。就像它的名稱那樣,最少知識原則適用與門面模式的用例,並且原則這個詞是指導方針的意思,而不是嚴格遵守的意思,並且只有在有需求的時候才用。

問答

問.子系統可以有多個門面嗎?
答:是的,可以爲一組子系統組件實現多個門面。

問.最少知識原則的缺點是什麼?
答:門面提供了一個簡化的接口供客戶端與子系統交互。本着提供簡化接口的精神,應用可能會建立多個不必要的接口,這增加了系統的複雜性並且降低了運行時的性能。

問.客戶端可以獨立訪問子系統嗎?
答:是的,事實上,由於門面模式提供了簡化的接口,這使得客戶端不必擔心子系統的複雜性。

問.門面是否可以添加自己的功能?
答:門面可以將其“想法”添加到子系統中,例如確保子系統的改進順序由門面來決定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章