簡述
中介者模式(Mediator Pattern)用一個中介對象來封裝一系列的對象互動。中介者使各對象不需要顯式地互相引用,進而使其耦合松散,而且可以獨立地改變它們之間的互動。
版權所有:一去丶二三裡,轉載請注明出處:
http://blog.csdn.net/liang19890820UML 結構圖:
- Mediator(抽象中介者):為 Colleague 對象之間的通信定義接口。
- ConcreteMediator(具體中介者):實作 Mediator 接口,并需要了解和維護各個 Colleague 對象,負責協調他們之間的通信。
- Colleague(抽象同僚類):定義與其他 Colleague 通信的接口。
- ConcreteColleague (具體同僚類):實作 Colleague 接口,并通過 Mediator 與其他 Colleague 進行溝通。
中介者是對象的通信中心。當一個對象需要與另一個對象通信時,它不會直接調用另一個對象。相反,它會調用中介者對象,其主要職責是将消息路由到目标對象。它允許開發人員不必管理對象之間的連結。
優點:
- 中介者模式簡化了對象之間的互動,它用中介者和同僚的一對多互動代替了原來同僚之間的多對多互動,一對多關系更容易了解、維護和擴充,将原本難以了解的網狀結構轉換成相對簡單的星型結構。
- 中介者模式可将各同僚對象解耦。中介者有利于各同僚之間的松耦合,可以獨立地改變和複用每一個同僚和中介者,增加新的中介者和新的同僚類都比較友善,更好地符合“開閉原則”。
- 可以減少子類生成,中介者将原本分布于多個對象間的行為集中在一起,改變這些行為隻需生成新的中介者子類即可,這使各個同僚類可被重用,無須對同僚類進行擴充。
缺點:
- 如果存在大量同僚之間的互動,中介者将會變得非常複雜,使得系統難以維護。
- 系統中對象之間存在比較複雜的引用關系,導緻它們之間的依賴關系結構混亂而且難以複用該對象。
- 想通過一個中間類來封裝多個類中的行為,而又不想生成太多的子類。
中介 - 客戶與房東之間的橋梁
說起中介,很多人第一印象是房産中介,專門負責新房、二手房買賣、以及租房等業務。
奔波在一線城市的人,想必都經曆過找房的辛酸(北漂的我默默地路過),不通過中介,想找到一個合适的小窩?不存在的。。。社群駐守、客戶介紹、網絡拓客、花錢買房源資訊,對于中介來說,這些簡直都是輕車熟路,房源哪裡逃!更可怕的是,前一秒是獨家,下一秒就是千百家。
這裡,中介是對象的通信中心。當房東需要與租客通信時,他們之間不會直接互動,而是通過中介将消息發送給目标對象。
建立抽象中介者
由于中介需要和所有參與者打交道,是以它除了注冊參與者之外,還需要将發送者的消息傳遞出去:
// mediator.h
#pragma once
#include "colleague.h"
#include <list>
class IColleague;
// 抽象中介者
class IMediator
{
public:
// 注冊參與者
virtual void registerColleague(IColleague* colleague) { m_colleagues.emplace_back(colleague); }
const std::list<IColleague*>& getColleagues() const { return m_colleagues; }
// 将發送者的消息發送給所有參與者
virtual void distributeMessage(const IColleague* sender, const std::string& message) const = 0;
private:
std::list<IColleague*> m_colleagues;
};
建立具體中介者
具體中介者的職責是周遊所有的參與者,将發送者的消息通知到每一個人:
// concrete_mediator.h
#ifndef CONCRETE_MEDIATOR_H
#define CONCRETE_MEDIATOR_H
#include "mediator.h"
// 具體中介者
class ConcreteMediator : public IMediator
{
public:
// 将發送者的消息發送給所有參與者(但不包括發送者自己)
virtual void distributeMessage(const IColleague* sender, const std::string& message) const override {
for (const IColleague* c : getColleagues())
if (c != sender) // 不要将消息發送給自己
c->receiveMessage(sender, message);
}
};
#endif // CONCRETE_MEDIATOR_H
注意: 這裡需要添加限制
c != sender
,防止将消息回傳給發送者自己。
建立抽象同僚
由于房東和租客均由同僚類表示,是以既需要(房東)發送消息,又需要(租客)接收消息:
// colleague.h
#pragma once
#include "mediator.h"
#include <string>
class IMediator;
// 抽象同僚類
class IColleague
{
public:
IColleague(const std::string& name) : m_strName (name) {}
std::string getName() const { return m_strName; }
// 通過中介者,将自己的消息釋出出去
virtual void sendMessage(const IMediator& mediator, const std::string& message) const = 0;
// 接收來自發送者的消息
virtual void receiveMessage(const IColleague* sender, const std::string& message) const = 0;
private:
std::string m_strName;
};
建立具體同僚
在内部,具體的消息發送由中介者完成:
// concrete_colleague.h
#ifndef CONCRETE_COLLEAGUE_H
#define CONCRETE_COLLEAGUE_H
#include "colleague.h"
#include <iostream>
// 具體同僚類
class ConcreteColleague : public IColleague
{
public:
using IColleague::IColleague;
// 通過中介者,将自己的消息釋出出去
virtual void sendMessage(const IMediator& mediator, const std::string& message) const override {
mediator.distributeMessage(this, message);
}
private:
// 接收來自發送者的消息
virtual void receiveMessage(const IColleague* sender, const std::string& message) const override {
std::cout << getName() << " received the message from "
<< sender->getName() << ": " << message << std::endl;
}
};
#endif // CONCRETE_COLLEAGUE_H
建立用戶端
找房啦!一旦房東将房子挂出去,中介便會通知所有需要租房的人:
// main.cpp
#include "concrete_colleague.h"
#include "concrete_mediator.h"
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if(p){delete(p); (p)=NULL;} }
#endif
int main()
{
// 房東
IColleague *landlord = new ConcreteColleague("Tom");
// 租客
IColleague *jerry = new ConcreteColleague("Jerry");
IColleague *tuffy = new ConcreteColleague("Tuffy");
// 中介者 - 添加租客
ConcreteMediator mediator;
mediator.registerColleague(jerry);
mediator.registerColleague(tuffy);
// 房東通過中介将消息發送出去
landlord->sendMessage(mediator, "Xi'erqi, two bedroom house, 6000/month.");
SAFE_DELETE(jerry);
SAFE_DELETE(tuffy);
getchar();
return 0;
}
輸出如下:
Jerry received the message from Tom: Xi’erqi, two bedroom house, 6000/month.
Tuffy received the message from Tom: Xi’erqi, two bedroom house, 6000/month.