假设有3个对象Car,Bus,Truck,都向消息总线注册了消息,消息类型为std::function<void(int)>,其中Car,Bus在注册时指定了主题。这三个对象在注册完消息后,希望能收到感兴趣的消息并处理,并不关心是谁给他们发送消息;另外,有个Subject会发送消息,Subject并不关心实惠收到消息。
3个对象和Subject对象没有耦合关系,它们之间唯一的联系就是消息总线。MessageBus的一个应用示例如下:
#include "MessageBus.hpp"
MessageBus g_bus;
const string Topic = "Drive";
struct Subject
{
void SendReq(const string& topic)
{
g_bus.SendReq<void, int>(500,topic);
}
};
Struct Car
{
Car()
{
g_bus.Attach([this](int speed){ Drive(speed); }, Topic);
}
void Drive(int speed)
{
cout << "Car drive " << speed << endl;
}
};
Struct Bus
{
Bus()
{
g_bus.Attach([this](int speed){ Drive(speed); }, Topic);
}
void Drive(int speed)
{
cout << "Bus drive " << speed << endl;
}
};
Struct Truck
{
Truck()
{
g_bus.Attach([this](int speed){ Drive(speed); });
}
void Drive(int speed)
{
cout << "Truck drive " << speed << endl;
}
};
void TestBus()
{
Subject subject;
Car car;
Bus bus;
Truck truck;
subject.SendReq(Topic);
cout << "-------" << endl;
subject.SendReq("");
g_bus.Remove<void, int>();
subject.SendReq("");
}
输出结果如下:
Car drive
Bus drive
-------
Truck drive
subject发送"Drive"主题的消息时,Car和Bus接收消息并处理;subject发送""消息时,Truck接收消息并处理。消息总线删除std::funciton<void(int)>消息后,接收者不再接收消息。
需求变复杂:在3个对象接收并处理完消息后,需要再告诉发送者消息已经处理完成。
MessageBus的应用示例如下:
#include "MessageBus.hpp"
MessageBus g_bus;
const string Topic = "Drive";
const string CallBackTopic = "DriveOk";
struct Subject
{
Subject
{
// 主题也注册消息
g_bus.Attach([this]{ DriveOk(); }, CallBackTopic);
}
void SendReq(const string& topic)
{
g_bus.SendReq<void, int>(500,topic);
}
void DriveOK()
{
cout << "drive ok" << endl;
}
};
Struct Car
{
Car()
{
g_bus.Attach([this](int speed){ Drive(speed); }, Topic);
}
void Drive(int speed)
{
cout << "Car drive " << speed << endl;
// 接收者处理消息后,回复消息给发送者
g_bus.SendReq<void>(CallBackTopic);
}
};
Struct Bus
{
Bus()
{
g_bus.Attach([this](int speed){ Drive(speed); }, Topic);
}
void Drive(int speed)
{
cout << "Bus drive " << speed << endl;
// 接收者处理消息后,回复消息给发送者
g_bus.SendReq<void>(CallBackTopic);
}
};
Struct Truck
{
Truck()
{
g_bus.Attach([this](int speed){ Drive(speed); });
}
void Drive(int speed)
{
cout << "Truck drive " << speed << endl;
// 接收者处理消息后,回复消息给发送者
g_bus.SendReq<void>(CallBackTopic);
}
};
void TestBus()
{
Subject subject;
Car car;
Bus bus;
Truck truck;
subject.SendReq(Topic);
cout << "-------" << endl;
subject.SendReq("");
g_bus.Remove<void, int>();
subject.SendReq("");
}
输出结果如下:
Car drive
drive ok
Bus drive
drive ok
-------
Truck drive
drive ok
可以看到用户只需维护主题与消息,对象(Car,Bus,Truck)之间都是松耦合。
注意:
消息总线的使用场景适用于对象很多且关系复杂的时候,对于对象较少且关系简单的不要使用消息总结使得简单问题复杂化。