版本一
#include <iostream>
#include <vector>
#include <unordered_map>
#include <functional>
#include <mutex>
class Subscriber {
public:
virtual void update(const std::string& topic, const std::string& message) = 0;
};
class Publisher {
public:
void subscribe(const std::string& topic, Subscriber* subscriber) {
std::lock_guard<std::mutex> lock(mutex_);
subscribers[topic].push_back(subscriber);
}
void unsubscribe(const std::string& topic, Subscriber* subscriber) {
std::lock_guard<std::mutex> lock(mutex_);
if (subscribers.find(topic) != subscribers.end()) {
auto& topicSubscribers = subscribers[topic];
topicSubscribers.erase(std::remove(topicSubscribers.begin(), topicSubscribers.end(), subscriber), \
topicSubscribers.end());
}
}
void publish(const std::string& topic, const std::string& message) {
std::lock_guard<std::mutex> lock(mutex_);
if (subscribers.count(topic) > 0) {
auto& topicSubscribers = subscribers[topic];
for (auto subscriber : topicSubscribers) {
subscriber->update(topic, message);
}
}
}
private:
std::unordered_map<std::string, std::vector<Subscriber*>> subscribers;
std::mutex mutex_;
};
class ConcreteSubscriber : public Subscriber {
std::string name_;
public:
ConcreteSubscriber(const std::string& name) : name_(name) {}
void update(const std::string& topic, const std::string& message) override {
std::cout << name_ << " received message on topic " << topic << ": " << message << std::endl;
}
};
int main() {
Publisher publisher;
ConcreteSubscriber subscriber1("Subscriber 1");
ConcreteSubscriber subscriber2("Subscriber 2");
ConcreteSubscriber subscriber3("Subscriber 3");
publisher.subscribe("Topic 1", &subscriber1);
publisher.subscribe("Topic 1", &subscriber2);
publisher.subscribe("Topic 2", &subscriber2);
publisher.subscribe("Topic 2", &subscriber3);
publisher.publish("Topic 1", "Hello from Topic 1");
publisher.publish("Topic 2", "Hello from Topic 2");
publisher.unsubscribe("Topic 1", &subscriber2);
publisher.publish("Topic 1", "Hello again from Topic 1");
publisher.publish("Topic 2", "Hello again from Topic 2");
return 0;
}
版本二
#include <iostream>
#include <vector>
#include <unordered_map>
#include <functional>
#include <mutex>
#include <algorithm>
class Subscriber;
class Publisher
{
std::unordered_map<std::string, std::vector<Subscriber *>> _subscribers;
std::mutex _mutex;
public:
void subscribe(const std::string &topic, Subscriber *subscriber)
{
std::lock_guard<std::mutex> lock(_mutex);
_subscribers[topic].push_back(subscriber);
}
void unsubscribe(const std::string &topic, Subscriber *subscriber)
{
std::lock_guard<std::mutex> lock(_mutex);
if (_subscribers.find(topic) != _subscribers.end())
{
auto &topicSubscribers = _subscribers[topic];
topicSubscribers.erase(std::remove(topicSubscribers.begin(), topicSubscribers.end(), subscriber),
topicSubscribers.end());
}
}
void unsubscribeAllTopics(Subscriber *subscriber)
{
std::lock_guard<std::mutex> lock(_mutex);
for (auto &it : _subscribers)
{
auto &topicSubscribers = it.second;
topicSubscribers.erase(std::remove(topicSubscribers.begin(), topicSubscribers.end(), subscriber),
topicSubscribers.end());
}
}
void publish(const std::string &topic, const std::string &message);
};
class Subscriber
{
public:
virtual void update(const std::string &topic, const std::string &message) = 0;
void subscribeToTopics(Publisher &publisher, const std::vector<std::string> &topics)
{
for (const auto &topic : topics)
{
publisher.subscribe(topic, this);
}
}
void unsubscribeFromTopics(Publisher &publisher, const std::vector<std::string> &topics)
{
for (const auto &topic : topics)
{
publisher.unsubscribe(topic, this);
}
}
void unsubscribefromAllTopics(Publisher &publisher)
{
publisher.unsubscribeAllTopics(this);
}
};
void Publisher::publish(const std::string &topic, const std::string &message)
{
std::lock_guard<std::mutex> lock(_mutex);
if (_subscribers.count(topic) > 0)
{
for (const auto &subscriber : _subscribers[topic])
{
subscriber->update(topic, message);
}
}
}
class ConcreteSubscriber : public Subscriber
{
std::string _name;
public:
ConcreteSubscriber(const std::string &name) : _name(name) {}
void update(const std::string &topic, const std::string &message) override
{
std::cout << _name << " received message on topic " << topic << ": " << message << std::endl;
}
};
int main()
{
Publisher publisher;
std::vector<std::string> topics1 = {"Topic 1", "Topic 2"};
std::vector<std::string> topics2 = {"Topic 1", "Topic 3"};
ConcreteSubscriber subscriber1("Subscriber 1");
ConcreteSubscriber subscriber2("Subscriber 2");
subscriber1.subscribeToTopics(publisher, topics1);
subscriber2.subscribeToTopics(publisher, topics2);
publisher.publish("Topic 1", "Hello from Topic 1");
publisher.publish("Topic 2", "Hello from Topic 2");
publisher.publish("Topic 3", "Hello from Topic 3");
subscriber1.unsubscribeFromTopics(publisher, topics1);
subscriber2.unsubscribefromAllTopics(publisher);
publisher.publish("Topic 1", "Hello from Topic 1");
publisher.publish("Topic 2", "Hello from Topic 2");
publisher.publish("Topic 3", "Hello from Topic 3");
return 0;
}```