带有类型信息的观察者模式(C ++) [英] Observer pattern with type information (C++)
问题描述
我试图在c ++中实现一个自定义版本的Observer模式。
i'm trying to implement a custom version of an Observer pattern in c++.
这些是我的类(只是接口):
These are my classes (just interface):
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的类都可以注册自身作为观察具有行为的观察值。
Each class implementing Observer can register itself as observing an Observable with a behaviour.
观察者可以通过notifyBehaviour向所有感兴趣的人通知其操作。
The Observable can notify its actions with "notifyBehaviour" to everyone interested.
每个观察者将通过其方法通知通知。
Each Observer listening will be notified via its method "notified".
上面的工作完美。无论如何在上面的例子中:
The above works perfectly. Anyway in the example above:
void notified(std::string behaviour, Observable * observed){
if (behaviour == "jumping"){
// ...
}
我想使用Observable *我传递在通知对象做一些事情。不幸的是,我必须做这样的事情:
i'd like to use the Observable * i'm passing to do something on the notifying object. Unfortunately i'll have to do something like this:
void notified(std::string behaviour, Observable * observed){
if (behaviour == "jumping"){
auto pointer = dynamic_cast<B *>(observed);
if (pointer)
pointer->doSomethingElse();
}
}
这很丑陋,可能会产生问题。例如,观察两个不同的跳跃实体需要多个等待正确的实体。
That's ugly and will probably create problems. For example observing two different jumping entities will need multiple castings waiting for the right one.
我的问题是:是否可能通过一些RTTI或调用一个重载的函数或模板具有正确的对象类型?我想要:
My question is: is it possible to pass some RTTI or call an overloaded function or a template having already the right object type? I'd like to have:
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 !
}
}
};
所以我只需要实现我想听的各种对象类型。
so i just need to implement the various object types i'd like to listen.
我尝试过继承,模板,boost :: any,但还是没有运气。
I've tried with inheritance, templates, boost::any but still without luck.
p>
推荐答案
我最近在一些项目中做了这个。基本思想:
I have done this recently in a couple of projects. The basic idea:
我创建了一个基类(Notified),它为您希望接收的每个接口提供一个虚拟方法:
I created a base class (Notified) that has a virtual method for each interface you wish to receive:
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)和调用它们的方法:
I created a singleton to act as a central point to hold which things you want to send messages to (derived from Notified) and methods to call them:
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类尝试创建模板方法很有诱惑力:
It is tempting to try and make a template method for the Notified class:
template <typename T>
virtual bool Notify(NOTIFIED_EVENT_TYPE_T eventType, const T& value)
但你不能需要是虚拟的,所以你可以让你的派生类处理它。我想了解更深入的做一个模板(元模板东西),但我认为这将混淆一个简单的使用和可以理解的设计。
But you cannot because it needs to be virtual so you can have your derived class handle it. I thought about digging deeper into doing it as a template (meta template stuff), but I think that would confuse an otherwise generally simple to use and understandable design.
这个设计的要点是:
1.您可以通过编译过程直接检查,直接调用您的Notified派生类。
2.如果你不为你的函数实现一个处理程序,你可以让Notifier类在返回false时抛出一个异常。
3.在Notified派生类中为每个处理程序编写代码很简单:
The main point of this design is:
1. You get complete type safety calling your Notified derived classes, checked directly through the compile process.
2. If you don't implement a handler for your function, you can have the Notifier class throw an exception when you return false.
3. Writing code for each handler in a Notified derived class is trivial:
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;
}
};
我有这样的例子(在生活的各个阶段)在发现的帖子此处。
I have examples of this in (in various stages of life) in posts found here.
这对您有帮助吗?
这篇关于带有类型信息的观察者模式(C ++)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!