這篇文章比較短,修改自 寫給大家看的設計模式之中介者中的例子
中介者模式的定義和目的自不必說, 參考上文即可. 本文針對實現方式做一個補充.
中介者模式增加了一個第三方對象(中介者)來控制兩個對象(同事)間的交互. 有助于對彼此通信的解耦, 畢竟他們并不需要關心對方的實現細節.
例子中給出了ChatRoom
作為第三方中介者, 而User
作為真正的通信對象, 每個用戶發送的消息實際上是在ChatRoom
中進行了廣播. 對于通信的接耦有兩種方式:
-
User
調用第三方對象的方法, 進行消息或者動作的傳遞, 比如上文中的實現即調用了ChatRoom
的ShowMessage
方法. - 不同的對象不通過方法調用來交互, 而是通過消息總線傳遞消息體.
實現
這里針對第二點給出實現, 這里利用boost::signal2來實現ChatRoom
對消息體訂閱, 各User
對象實例負責信息的發布.
#include <iostream>
#include <string>
#include <ctime>
#include <iomanip>
#include <boost/signals2/signal.hpp>
using namespace std;
using namespace boost::signals2;// Message
struct EventMessage {virtual ~EventMessage() = default;virtual void showMessage() const = 0;
};
struct ChatMessage : public EventMessage {string username;string message;ChatMessage(const string &username, const string &message) : username(username), message(message) {}void showMessage() const override {std::time_t now = std::time(nullptr);std::cout << std::put_time(std::localtime(&now), "%Y-%m-%d %H:%M:%S") << "[" << username << "]: " << message << std::endl;}
};// EventBus -> ChatRoom
struct EventBus {signal<void(EventMessage *)> sig;EventBus() {sig.connect([](EventMessage *e){ChatMessage *mess = dynamic_cast<ChatMessage *>(e);if(mess) {mess->showMessage();}});}
};// instance
struct User {string name_;EventBus &event;User(const string &name_, EventBus &event) : name_(name_), event(event) {}void send(const string &message) {ChatMessage chatMessage(name_, message);event.sig(&chatMessage);}
};int main() {EventBus bus;User john("John Doe", bus);User jane("Jane Doe", bus);john.send("Hi, there!");jane.send("Hey!");
}
優點
當前的例子的業務模型實際比較簡單, 如果業務變的復雜(比如還要支持私信即可定點sendMessage新增廣播消息即每個用戶需要支持received), 如果繼續使用方法傳遞,那么ChatRoom
為了和User
通信,互相調用來調用去,很容易暈掉, 而只用通過訂閱事件進行的數據傳遞,數據生產者和使用者在注冊的時候就清晰明了,不容易出錯.