为了优化公司项目的软件架构,确保对象数据传递高效即时,特用C++模板设计了发布者和订阅者,现将代码公布如下,以提高C++爱好者的激情。
#ifndef EEB2E066_350D_4A6B_93CF_BA7C825588A4
#define EEB2E066_350D_4A6B_93CF_BA7C825588A4
#include <string>
#include <vector>
#include <map>
#include <iostream>
class Publisher;
template <typename T>
class SubscribeImpl
{
public:
virtual void dataChanged(Publisher *sender, const T &data) = 0;
};
class Subscriber
{
private:
std::string _name;
protected:
Subscriber(const std::string &name) : _name(name) {}
public:
virtual ~Subscriber() {}
std::string getSubscriberName() const { return _name; }
template <typename T>
SubscribeImpl<T> *getInterface()
{
return dynamic_cast<SubscribeImpl<T> *>(this);
}
bool subscribe(Publisher *publisher, const std::string &topic);
};
class Publisher
{
private:
std::string _name;
std::map<std::string, std::vector<Subscriber *>> _subscribers;
public:
Publisher(const std::string &name = "") : _name(name)
{
std::cout << "Publisher::Publisher()" << std::endl;
}
virtual ~Publisher()
{
std::cout << "Publisher::~Publisher()" << std::endl;
}
std::string getPublisherName() { return _name; }
void addSubscriber(const std::string &topic, Subscriber *subscriber)
{
if (_subscribers.count(topic) > 0)
{
auto &subscribers = _subscribers[topic];
subscribers.push_back(subscriber);
}
else
{
std::vector<Subscriber *> subscribers;
subscribers.push_back(subscriber);
_subscribers[topic] = subscribers;
}
}
template <typename T>
void pubish(const std::string &topic, const T &value)
{
if (_subscribers.count(topic) == 0)
return;
auto &subscribers = _subscribers[topic];
for (auto &subscriber : subscribers)
{
auto impl = subscriber->getInterface<T>();
if (impl != nullptr)
impl->dataChanged(this, value);
}
}
template <typename T>
void publish(const std::string &topic, const T *value)
{
if (_subscribers.count(topic) == 0)
return;
auto &subscribers = _subscribers[topic];
for (auto &subscriber : subscribers)
{
auto impl = subscriber->getInterface<T>();
if (impl != nullptr)
impl->dataChanged(this, *value);
}
}
std::vector<std::string> getTopics() const
{
auto result = std::vector<std::string>();
for (auto &subscriber : _subscribers)
{
result.push_back(subscriber.first);
}
return result;
}
};
bool Subscriber::subscribe(Publisher *publisher, const std::string &topic)
{
if (publisher == nullptr)
return false;
publisher->addSubscriber(topic, this);
return true;
}
#endif /* EEB2E066_350D_4A6B_93CF_BA7C825588A4 */
下面代码是发布者和订阅者的demo,仅供参考。
#include <iostream>
#include "subscriber.h"
class SubscriberA : public Subscriber,
public SubscribeImpl<int>,
public SubscribeImpl<double>
{
public:
SubscriberA(const std::string &name) : Subscriber(name) {}
~SubscriberA() {}
void dataChanged(Publisher *sender, const int &value)
{
std::cout << "publisher :" << sender->getPublisherName() << "\tSubscriber: " << getSubscriberName() << ":" << value << std::endl;
}
void dataChanged(Publisher *sender, const double &value)
{
std::cout << "publisher :" << sender->getPublisherName() << "\tSubscriber: " << getSubscriberName() << ":" << value << std::endl;
}
};
class SubscriberB : public Subscriber,
public SubscribeImpl<int>,
public SubscribeImpl<double>
{
public:
SubscriberB(const std::string &name) : Subscriber(name) {}
~SubscriberB() {}
void dataChanged(Publisher *sender, const int &value)
{
std::cout << "publisher :" << sender->getPublisherName() << "\tSubscriber: " << getSubscriberName() << ":" << value << std::endl;
}
void dataChanged(Publisher *sender, const double &value)
{
std::cout << "publisher :" << sender->getPublisherName() << "\tSubscriber: " << getSubscriberName() << ":" << value << std::endl;
}
};
class SubscriberC : public Subscriber,
public SubscribeImpl<int>
{
public:
SubscriberC(const std::string &name) : Subscriber(name) {}
~SubscriberC() {}
void dataChanged(Publisher *sender, const int &value)
{
std::cout << "publisher :" << sender->getPublisherName() << "\tSubscriber: " << getSubscriberName() << ":" << value << std::endl;
}
};
class PublisherA : public Publisher
{
public:
PublisherA(const std::string &name) : Publisher(name)
{
std::cout << "PublisherA::PublisherA()" << std::endl;
}
virtual ~PublisherA()
{
std::cout << "PublisherA::~PublisherA()" << std::endl;
}
};
class PublisherB : public Publisher
{
public:
PublisherB(const std::string &name) : Publisher(name)
{
std::cout << "PublisherB::PublisherB()" << std::endl;
}
virtual ~PublisherB()
{
std::cout << "PublisherB::~PublisherB()" << std::endl;
}
};
int main(int argc, char *argv[])
{
PublisherA a("A发布者");
PublisherB b("B发布者");
SubscriberA *subA = new SubscriberA("subscriber A");
SubscriberB *subB = new SubscriberB("subscriber B");
SubscriberC *subC = new SubscriberC("subscriber C");
subA->subscribe(&a, "topic_1");
subA->subscribe(&a, "topic_2");
subB->subscribe(&a, "topic_1");
subB->subscribe(&a, "topic_2");
subC->subscribe(&a, "topic_1");
subC->subscribe(&a, "topic_2");
subA->subscribe(&b, "topic_1");
subA->subscribe(&b, "topic_2");
subB->subscribe(&b, "topic_1");
subB->subscribe(&b, "topic_2");
subC->subscribe(&b, "topic_1");
subC->subscribe(&b, "topic_2");
a.pubish<int>("topic_1", 15);
a.pubish<double>("topic_1", 3.14);
a.pubish<int>("topic_2", 25);
a.pubish<int>("topic_3", 35);
a.pubish<double>("topic_2", 1.414121);
b.pubish<int>("topic_1", 35);
b.pubish<double>("topic_1", 2.71828);
b.pubish<int>("topic_2", 35);
b.pubish<double>("topic_2", 2.71828);
delete subA;
delete subB;
delete subC;
return 0;
}
总结
订阅者与发布者是作者近期为了改善项目中对象间信息传输而设计的,属于作者开发经验的一次小结!欢迎小伙伴们一起讨论学习!