我正在尝试用c ++实现Observer模式的自定义版本。
这些是我的类(只是界面):
class Observer{
public:
void observe(std::string behaviour, Observable * observable);
void stopObserving(std::string behaviour, Observable * observable);
virtual void notified(std::string behaviour, Observable * observed);
// ...
};
class Observable{
public:
void notifyBehaviour(std::string behaviour);
// ...
};
可以像这样使用:
class A : public Observer{
public:
void notified(std::string behaviour, Observable * observed){
if (behaviour == "jumping"){
// ...
}
}
};
class B : public Observable{
public:
void jump(){
// ...
notifyBehaviour("jumping");
}
};
int main(){
A a;
B b;
a.observe("jumping", &b);
b.jump();
// ...
}
实现Observer的每个类都可以将自己注册为观察带有行为的Observable。
Observable可以通过“notifyBehaviour”向所有感兴趣的人通知其行为。
每个观察者监听都将通过其“通知”方法通知。
以上工作完美。无论如何在上面的例子中:
void notified(std::string behaviour, Observable * observed){
if (behaviour == "jumping"){
// ...
}
我想使用Observable *我传递给通知对象做一些事情。不幸的是,我必须做这样的事情:
void notified(std::string behaviour, Observable * observed){
if (behaviour == "jumping"){
auto pointer = dynamic_cast<B *>(observed);
if (pointer)
pointer->doSomethingElse();
}
}
那很难看,可能会产生问题。例如,观察两个不同的跳跃实体将需要多个铸件等待正确的一个。
我的问题是:是否可以传递一些RTTI或调用重载函数或具有正确对象类型的模板?我想要:
class A : public Observer{
public:
void notified(std::string behaviour, B * observed){
if (behaviour == "jumping"){
observed->doSomethingBlike();
// observed if of type B !
}
}
void notified(std::string behaviour, C * observed){
if (behaviour == "jumping"){
observed->doSomethingClike();
// observed if of type C !
}
}
};
所以我只需要实现我想听的各种对象类型。
我尝试过继承,模板,boost :: any但仍然没有运气。
感谢您的想法。
答案 0 :(得分:0)
在Observed类中声明一个纯虚方法。或者只是一个空的虚函数,所以不需要覆盖。
class Observed {
public:
virtual ~Observed();
Observed();
virtual void DoSomethingElse() {} // OR
//void DoSomethingElse() = NULL;
// rest of class
};
答案 1 :(得分:0)
我最近在几个项目中做过这个。基本理念:
我创建了一个基类(Notified),它为您希望接收的每个接口都有一个虚方法:
class Notified { public: virtual bool Notify(NOTIFIED_EVENT_TYPE_T eventType, uint32 value) { return false; }; virtual bool Notify(NOTIFIED_EVENT_TYPE_T eventType, ITEM_ID_T value) { return false; }; virtual bool Notify(NOTIFIED_EVENT_TYPE_T eventType, const string& value) { return false; }; virtual ~Notified(); };
我创建了一个单例,作为一个中心点,用于保存要向其发送消息的内容(从Notified派生)和调用它们的方法:
class Notifier : public SingletonDynamic<Notifier>
{
private:
... detail omitted...
public:
virtual void Reset();
virtual bool Init() { Reset(); return true; }
virtual void Shutdown() { Reset(); }
void Attach(Notified* observer, NOTIFIED_EVENT_TYPE_T eventType);
// Detach for a specific event
void Detach(Notified* observer, NOTIFIED_EVENT_TYPE_T eventType);
// Detach for ALL events
void Detach(Notified* observer);
// This template function (defined in the header file) allows you to
// add interfaces to Notified easily and call them as needed. Variants
// will be generated at compile time by this template.
template <typename T>
bool Notify(NOTIFIED_EVENT_TYPE_T eventType, const T& value)
{
...detail omitted
}
/* Used for CPPUnit. Could create a Mock...maybe...but this seems
* like it will get the job done with minimal fuss. For now.
*/
// Return all events that this object is registered for.
vector<NOTIFIED_EVENT_TYPE_T> GetEvents(Notified* observer);
// Return all objects registered for this event.
vector<Notified*> GetNotified(NOTIFIED_EVENT_TYPE_T event);
};
尝试为Notified类创建模板方法很有吸引力:
template <typename T>
virtual bool Notify(NOTIFIED_EVENT_TYPE_T eventType, const T& value)
但你不能因为它需要是虚拟的,所以你可以让你的派生类来处理它。我想深入挖掘它作为一个模板(元模板的东西),但我认为这会混淆一个通常简单易用和易懂的设计。
这个设计的要点是:
1.通过编译过程直接检查,您可以获得完整的类型安全性调用Notified派生类。
2.如果没有为函数实现处理程序,则可以让Notifier类在返回false时抛出异常。
3.为Notified派生类中的每个处理程序编写代码是微不足道的:
class MyNotified : public Notified
{
virtual bool Notified(NOTIFIED_EVENT_T evt, uint32 value)
{
bool result = true;
switch(evt)
{
case EVT_1:
...do something...
break;
default:
result = false;
}
return result;
}
};
我在here找到的帖子中(生活的各个阶段)都有这样的例子。
这有用吗?