最近我开始实现一个使用“观察者模式”的消息调度系统:这里没什么特别的。当我开发它时,我认为从“主题”发送“消息”对象会很好,这些对象可能彼此根本不同,并且可以从许多“观察者”那里读取。
这些不同的消息采取不同消息类别的形式(例如,想想“用户注销消息”、“屏幕模式切换”和“音量级别已更改”,所有这些都需要不同的信息),很快我发现“观察者" 不需要知道我想要创建的每条不同的信息(至少可以说,这将是……不可持续的)。相反,我希望每个观察者都能够对特定类型的消息做出反应。
因此,为了制作一些东西,我认为双重调度可能是我的选择。经过一点点我得到了这篇文章(c ++ 11只是因为for循环):
#include <iostream>
#include <vector>
#include <string>
/**
* A few forward declarations.
*/
class Message_base;
class Message_type_a;
class Message_type_b;
/**
* Base observer...
*/
class Observer_base
{
public:
/**
* All these implementations are empty so we don't have to specify them
* in every single derived class.
*/
virtual void get_message(const Message_base&) {}
virtual void get_message(const Message_type_a&) {}
virtual void get_message(const Message_type_b&) {}
};
/**
* Specification of all message types.
*/
class Message_base
{
public:
/**
* This is the method that will implement the double dispatching in all
* derived classes.
*/
virtual void be_recieved(Observer_base &r) const=0; //Now that's a nasty method name.
};
class Message_type_a:public Message_base
{
private:
int integer_value;
public:
Message_type_a(int v):integer_value(v) {}
int get_integer_value() const {return integer_value;}
void be_recieved(Observer_base &r) const {r.get_message(*this);}
};
class Message_type_b:public Message_base
{
private:
std::string string_value;
public:
Message_type_b(const std::string v):string_value(v) {}
std::string get_string_value() const {return string_value;}
void be_recieved(Observer_base &r) const {r.get_message(*this);}
};
/**
* This is the base clase for the Subject... Notice that there are no virtual
* methods so we could as well instantiate this class instead of derive it.
*/
class Subject_base
{
private:
std::vector<Observer_base *> observers;
public:
void emit_message(const Message_base& m) {for(auto o : observers) m.be_recieved(*o);} //Again, nasty to read since it's... backwards.
void register_observer(Observer_base * o) {observers.push_back(o);}
};
/**
* Now we will create a subject class for the sake of it. We could just call the
* public "emit_message" from main passing Message objects.
*/
class Subject_derived:public Subject_base
{
public:
void emit_message_a(int v) {emit_message(Message_type_a(v));}
void emit_message_b(const std::string v) {emit_message(Message_type_b(v));}
};
/**
* This gets fun... We make two observers. One will only get type_a messages
* and the other will get type_b.
*/
class Observer_type_a:public Observer_base
{
private:
int index; //We will use it to identify the observer.
public:
Observer_type_a(int i):index(i) {}
void get_message(const Message_type_a& m) {std::cout<<"Observer_type_a ["<<index<<"] : got type_a message : "<<m.get_integer_value()<<std::endl;}
};
class Observer_type_b:public Observer_base
{
private:
std::string name; //Merely to identify the observer.
public:
Observer_type_b(const std::string& n):name(n) {}
void get_message(const Message_type_b& m) {std::cout<<"Observer_type_b ["<<name<<"] : got type_b message : "<<m.get_string_value()<<std::endl;}
};
/**
* Stitch all pieces together.
*/
int main(int argc, char ** argv)
{
Observer_type_a o_a1(1);
Observer_type_a o_a2(2);
Observer_type_b o_b1("Sauron");
Observer_type_b o_b2("Roverandom");
Subject_derived s_a;
s_a.register_observer(&o_a1);
s_a.register_observer(&o_b1);
s_a.emit_message_a(23);
s_a.emit_message_b("this is my content");
s_a.register_observer(&o_a2);
s_a.register_observer(&o_b2);
s_a.emit_message_a(99);
s_a.emit_message_b("this is my second content");
//gloriously exit.
return 0;
}
为了清楚起见,我将在这里说出我的目标:
- 能够从主题发送许多不同的消息。
- 让观察者专门化他们忽略不适合他们的每条消息(如果根本不发送它们会更好,但我知道我可以注册不同的观察者组)。
- 避免 RTTI 和派生类转换。
我的问题来了:我是否错过了一个更简单的实现来实现我的目标?
值得一提的是,将使用此系统的系统不会有那么多观察者,可能同时出现的对象可能少于十个。