[Python設計模式] 第25章 聯合國維護世界和平——中介者模式

github地址:https://github.com/cheesezh/python_design_patternspython

題目背景

聯合國在世界上就是中介者的角色,各國之間的關係複雜,相似不一樣的對象和對象之間的關係,這就要求對象之間須要知道其餘全部對象,儘管將一個系統分割成許多對象一般能夠增長其可複用性,可是對象間相互鏈接的激增優惠下降其可複用性。大量的鏈接使得一個對象不可能在沒有其餘對象的支持下工做,系統表現爲一個不可分割的總體,因此,對系統的行爲進行任何較大的改動就十分困難了。git

這裏能夠應用「迪米特法則」,若是兩個類沒必要彼此直接通信,那麼這兩個類就不該該發生直接的相互做用。若是其中一個類須要調用另外一個類的某一種方法的話,能夠經過第三者轉發這個調用。也就是說,國與國之間的關係,徹底能夠經過聯合國這個中介者來維持,而沒必要直接通訊。github

中介者模式

中介者模式,用一箇中介對象來封裝一系列的對象交互。中介者使各個對象不須要顯示的相互引用,從而使其耦合鬆散,並且能夠獨立地改變它們之間的交互。[DP]安全

中介者模式主要包括如下幾個類:設計

  • Colleague叫作抽象同事類,而ConcretColleague是具體同事類,每一個具體同事只知道本身的行爲,而不瞭解其餘同事類的狀況,但它們卻都認識中介者對象;
  • Mediator是抽象中介者,定義了同事對象到中介者對象的接口,ConcretMediator是具體中介者對象,實現抽象類的方法,它須要知道全部具體同事類,並從具體同事接收消息,向具體同事對象發出命令。
from abc import ABCMeta, abstractmethod


class Mediator():
    """
    抽象中介者
    """
    
    __metaclass__ = ABCMeta
    
    @abstractmethod
    def send(self, message, colleague):
        """
        定義一個抽象的發送消息方法,獲得同事對象和發送消息
        """
        pass
    
    
class Colleague():
    """
    抽象同事類
    """
    
    __metaclass__ = ABCMeta
    
    def __init__(self, mediator):
        """
        構造方法,獲得中介者對象
        """
        self.mediator = mediator
        
        
class ConcreteMediator(Mediator):
    """
    具體中介者
    """
    def __init__(self):
        """
        須要瞭解全部的具體同事對象
        """
        self.colleague1 = None
        self.colleague2 = None
        
    def send(self, message, colleague):
        """
        重寫發送消息的方法,根據對象做出選擇判斷,通知具體同事對象
        """
        if colleague == self.colleague1:
            self.colleague2.notify(message)
        else:
            self.colleague1.notify(message)
        
        
class ConcreteColleague1(Colleague):
    """
    具體同事類1
    """
    def send(self, message):
        self.mediator.send(message, self)
        
    def notify(self, message):
        print("同事1獲得消息:",message)
        
        
class ConcreteColleague2(Colleague):
    """
    具體同事類2
    """
    def send(self, message):
        self.mediator.send(message, self)
        
    def notify(self, message):
        print("同事2獲得消息:",message)
        
        
def main():
    m = ConcreteMediator()
    
    """
    讓兩個具體同事類認識中介者對象
    """
    c1 = ConcreteColleague1(m)
    c2 = ConcreteColleague2(m)
    
    """
    讓中介者認識各個具體同事類
    """
    m.colleague1 = c1
    m.colleague2 = c2
    
    """
    具體同事類對象發送消息都是經過中介者轉發
    """
    c1.send("吃飯了嗎?")
    c2.send("還沒,你請客麼?")
    
main()
同事2獲得消息: 吃飯了嗎?
同事1獲得消息: 還沒,你請客麼?

點評

因爲有了Mediator,使得ConcreteColleague1和ConcreteColleague2在發送消息和接收消息時實際上是經過中介者來完成,這就減小了它們之間的耦合度。code

題目

用程序模擬,美國和伊拉克之間的對話都是經過聯合國安理會做爲中介來完成。對象

from abc import ABCMeta, abstractmethod


class UnitedNations():
    """
    聯合國機構,抽象中介者
    """
    
    __metaclass__ = ABCMeta
    
    @abstractmethod
    def send(self, message, colleague):
        """
        定義一個抽象的發送消息方法,獲得同事對象和發送消息
        """
        pass
    
    
class Country():
    """
    國家類,抽象同事類
    """
    
    __metaclass__ = ABCMeta
    
    def __init__(self, mediator):
        """
        構造方法,獲得中介者對象
        """
        self.mediator = mediator
        
        
class UnitedNationsSecurityCouncil(Mediator):
    """
    聯合國安全理事會,具體中介者
    """
    def __init__(self):
        """
        須要瞭解全部的具體同事對象
        """
        self.colleague1 = None
        self.colleague2 = None
        
    def send(self, message, colleague):
        """
        重寫發送消息的方法,根據對象做出選擇判斷,通知具體同事對象
        """
        if colleague == self.colleague1:
            self.colleague2.notify(message)
        else:
            self.colleague1.notify(message)
        
        
class USA(Colleague):
    """
    美國,具體同事類1
    """
    def send(self, message):
        self.mediator.send(message, self)
        
    def notify(self, message):
        print("美國 獲得消息:",message)
        
        
class Iraq(Colleague):
    """
    伊拉克,具體同事類2
    """
    def send(self, message):
        self.mediator.send(message, self)
        
    def notify(self, message):
        print("伊拉克 獲得消息:",message)
        
        
def main():
    m = UnitedNationsSecurityCouncil()
    
    """
    讓兩個具體同事類認識中介者對象
    """
    c1 = USA(m)
    c2 = Iraq(m)
    
    """
    讓中介者認識各個具體同事類
    """
    m.colleague1 = c1
    m.colleague2 = c2
    
    """
    具體同事類對象發送消息都是經過中介者轉發
    """
    c1.send("吃飯了嗎?")
    c2.send("還沒,你請客麼?")
    
main()
伊拉克 獲得消息: 吃飯了嗎?
美國 獲得消息: 還沒,你請客麼?

點評

ConcretMediator這個類必需要知道全部ConcreteCollegue,這就使得ConcreteMediator責任太多,若是它出現問題,則整個系統都會出現問題。接口

中介者模式很容易在系統中應用,也很容易在系統中誤用。當系統出現「多對多」交互複雜的對象羣時,不要急於使用中介者模式,而要先反思你的系統在設計上是否合理。ci

中介者模式的優勢:get

  • Mediator的出現減小了各個Colleague的耦合,使得能夠獨立地改變和複用各個Colleague類和Mediator;
  • 因爲把對象如何協做進行了抽象,將中介做爲一個獨立的概念並將其封裝在一個對象中,這樣關注的對象就從對象各自自己的行爲轉移到它們之間的交互上來,也就是站在一個更宏觀的角度去看待系統。

中介者模式的缺點:

  • 因爲ConcreteMediator控制了集中化,因而就把交互複雜性變爲了中介者的複雜性,這就使得中介者會變得比任何一個ConcreteColleague都複雜。
相關文章
相關標籤/搜索