带有类型信息的观察者模式(C ++) [英] Observer pattern with type information (C++)

查看:133
本文介绍了带有类型信息的观察者模式(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆