設計模式之中介者模式

中介者模式

  中介者模式又名調停者模式。將一個系統分割成許多對象一般能夠增長其可複用性,可是對象間相互鏈接的激增又會下降其可複用性。由於大量的鏈接使得一個對象不可能在沒有其它對象的支持下工做,系統表現爲一個不可分割的總體,因此,對系統的行爲進行任何較大的改動就十分困難了。解決這個問題的辦法是兩個類之間不直接進行通訊,若是一個類須要調用另外一個類的方法的話,能夠經過第三者轉發這個調用。經過中介者模式,能夠將系統中的網狀結構變成以中介者爲中心的星狀結構,每一個具體的對象再也不經過直接的聯繫與另外一個對象發生相互做用,而是經過中介者對象與兩一個對象發生相互做用。中介者對象的設計,使得系統的結構不會由於新對象的引入形成大量的修改工做。ios

  中介者(Mediator)模式,用一箇中介對象來封裝一系列的對象交互。中介者使得各對象不須要顯式的互相引用,從而使得其耦合鬆散,並且能夠獨立的改變他們之間的交互。數組

中介者模式的UML類圖

Colleague叫作抽象同事類,而ConcreteColleague是具體同事類,每一個具體同事只知道本身的行爲,而不瞭解其餘同事類的狀況,但它們都認識中介者對象,Mediator是抽象中介者,定義了同事對象到中介者對象的接口,ConcreteMediator是具體中介者對象,實現抽象類的方法,它須要知道全部具體同事類,並從具體同事類接收消息,向具體同事對象發出命令。Mediator是否存在,取決於系統以後是否有擴展的可能,同事類發送消息,通常都是經過中介者對象來發送的,這意味着具體的同事類須要持有一箇中介者對象。ide

中介者模式的優缺點

優勢:函數

  1.Meditor的出現減小了各個Colleague的耦合,使得能夠獨立的改變和複用各個Colleague類和Mediator。this

  2.因爲把對象如何協做進行了抽象,將中介做爲一個獨立的概念並將其封裝在一個對象中,這樣關注的對象就從對象各自自己的行爲轉移到他們之間的交互上來,也就是站在一個更加宏觀的角度來看待系統。spa

缺點:設計

  1.因爲ConcreteMediator控制集中化,因而把就把交互複雜性變成了中介者的複雜性,這就使得中介者會變的比任何一個Concrete都複雜。code

使用場景:對象

  1.中介者模式通常應用於一組對象以定義良好可是複雜的方式進行通訊的場合,以及想定製一個分佈在多個類中的行爲,而又不想生成太多的子類的場合。blog

代碼示例

  問題模型:一個貨運體系,有負責集中發佈貨運信息的中介公司(對應於中介者模式中的Mediator),有貨主,當貨主有貨物須要運送時,要求本身註冊過的中介公司發佈這條貨運信息,中介公司再負責把這條中介信息廣播給全部向本公司註冊過的火車司機。這裏火車司機和貨主就至關因而具體的同事類。

1.抽象同事類(UML類圖中的Colleague類)

#ifndef COLLEAGUE_H_
#define COLLEAGUE_H_

//這個類即能表明貨主也能表明貨車司機,因此它須要同時具有接收消息和發送消息的能力
//在中介模式中消息的發送和接收都是經過中介者來完成的,具體同事類,發佈消息時要委託中介者發佈,而接收消息雖然是從中介者來接收,但其實是從其它具體同事類那裏接收信息的,
//你能夠把中介者當成一個布告牌
#include <string>
class Mediator;

class Colleague
{
protected:
   std::string m_strName;
   Mediator *m_Mediator{nullptr};    //使具體同事類認識中介者,在具體的同事類中,須要經過構造函數爲它賦值
public:
   virtual void sendMessage(const std::string strMessgae) const = 0;  //委託本身認識的中介者(m_Mediator)把這個消息發佈出去
   virtual void receiveMessage(const Colleague *objColleague,const std::string strMessage) const = 0; //經過中介者,接收來自於信息發佈者的消息
   virtual std::string getName() const = 0;
   Colleague() = default;
   virtual ~Colleague() = default;
};
#endif
Colleague

2.抽象中介者類(UML類圖中的Mediator類)

抽象中介者須要知道一個同事列表,因此必然須要維護一個同事類的數組,以及同事類向中介者註冊、註銷本身的方法。此外,任何同事類的消息都將經過中介者轉發,因此,中介者類還須要有一個Send方法負責轉發消息。

#ifndef MEDIATOR_H_
#define MEDIATOR_H_

#include <list>
#include <string>
class Colleague;

class Mediator
{
protected:
    std::list<Colleague *> m_listColleague;
public:
    //貨車司機向中介公司註冊本身
    void registerColleague(Colleague * objColleague)
    {
    m_listColleague.push_back(objColleague);
    }
    //貨車司機從中介公司註銷本身的帳號
    void removeColleague(Colleague *objColleague)
    {
    m_listColleague.remove(objColleague);
    }
    //中介公司接收貨主的消息,並把這條消息轉發給全部註冊了的貨車司機
   virtual void distributeMessage(const Colleague *objColleagus,const std::string strMessage) const = 0;
   Mediator() = default;
   virtual ~Mediator() = default;
};
#endif
Mediator

3.具體同事類(UML類圖中的ConcreteColleague類)

#ifndef CONCRETECOLLEAGUE_H_
#define CONCRETECOLLEAGUE_H_
//具體的同事類,在內部,具體的消息發送過程由中介者完成

#include "Colleague.h"
#include <iostream>
class Mediator;
class ConcreteColleague : public Colleague
{
public:
    std::string getName() const override
    {
    return m_strName;
    }
    void sendMessage(const std::string strMessage) const override;
    void receiveMessage(const Colleague* objColleague,const std::string strMessage) const override;
    ConcreteColleague(Mediator * objMediator,const std::string strName)
    {
    m_Mediator = objMediator;
    m_strName = strName;
    }
    ~ConcreteColleague() = default;
};
#endif

#include "ConcreteColleague.h"
#include "Mediator.h"

//委託中介者將消息發佈出去
void ConcreteColleague::sendMessage(const std::string strMessage) const
{  
    if(nullptr != m_Mediator)
    {
     m_Mediator->distributeMessage(this,strMessage);
    }
}

//接收從中介那裏分發的來自於其它同事類的消息
void ConcreteColleague::receiveMessage(const Colleague* objColleague,const std::string strMessage) const
{
    if(nullptr != m_Mediator)
    {
    std::cout << "Sender's Name is :"<< objColleague->getName() << "Message:" << strMessage << ".Receiver's name is :" << getName() << std::endl;
    }
}
ConcreteColleague

4.具體中介者類(UML類圖中的ConcreteMediator類)

#ifndef CONCRETEMEDIATOR_H_
#define CONCRETEMEDIATOR_H_

#include "Mediator.h"
//具體的中介者,在本例中,這個中介者的具體做用就是把來自於具體同事對象的消息,轉發給出發佈消息者以外,系統內的其它同事對象
class ConcreteMediator:public Mediator
{
public:
    void distributeMessage(const Colleague* objColleague,const std::string strMessage) const override;
    ConcreteMediator() = default;
    ~ConcreteMediator() = default;
};
#endif

#include "ConcreteMediator.h"
#include "Colleague.h"

void ConcreteMediator::distributeMessage(const Colleague* objColleague,const std::string strMessage) const
{
    for(auto value : m_listColleague)
    {
    //使用條件判斷,防止中介者將信息發佈者回傳給了本身
    if(objColleague != value)
    {
        value->receiveMessage(objColleague,strMessage);
    }
    }
}
ConcreteMediator

5.Client

#include "ConcreteMediator.h"
#include "ConcreteColleague.h"

using namespace std;
int main(int argc,char *argv[])
{
    //中介公司
    ConcreteMediator objConcreteMediator;
    //貨主,讓貨主認識中介公司
    ConcreteColleague objConcreteColleague(&objConcreteMediator,"SenderA");
    //貨主向中介公司註冊本身的帳戶
    objConcreteMediator.registerColleague(&objConcreteColleague);
    //貨車司機A,使得貨車司機認識中介公司
    ConcreteColleague objReceiverA(&objConcreteMediator,"ReceiverA");
    //貨車司機A向中介公司註冊本身的帳戶
    objConcreteMediator.registerColleague(&objReceiverA);
    
    //貨車司機B,使得貨車司機B認識中介公司
    ConcreteColleague objReceiverB(&objConcreteMediator,"ReceiverB");
    //貨車司機B向中介公司註冊本身的帳戶
    objConcreteMediator.registerColleague(&objReceiverB);
    
    //貨主委託中介公司將信息發佈出去
    objConcreteColleague.sendMessage("you ren ke yi bang wo ba zhe xie yu mi yun song dao qi tai xian ma?yun fei 1000/dun.");
    return (1);
}
Client
相關文章
相關標籤/搜索