c ++双重调度观察者通知

时间:2011-12-07 06:34:50

标签: c++ interface observer-pattern double-dispatch

以下是我目前正在排查的代码:

void CTimer::notify()
{
    std::vector<IObserver*>::iterator it;
    for(it=observers.begin();it!=observers.end();++it)
    {
        ITimerNotification* notification = new CTimerNotification(now());
        (*it)->readNotification(*notification);
    }
}

class CTimerNotification : public ITimerNotification
{
    public:
        CTimerNotification(const timeval& t)
        {
            time = t;
        }
    protected:
        timeval time;
    private:
        virtual ~CTimerNotification();
        virtual void read(const IObserver& o) const
        {
            o.update(*this);
        }
        virtual const timeval& getTime() const
        {
            return time;
        }
};

class IObserver
{
    public:
        virtual ~IObserver();
        virtual void readNotification(const INotification&) const=0;
        virtual void update(const INotification&) const=0;
};

class ITimerObserver : public IObserver
{
    public:
        virtual void update(const ITimerNotification&) const=0;
};

class TestObserver : public ITimerObserver
{
    public:
        virtual void readNotification(const INotification& n) const
        {
            n.read(*this);
        }
        virtual void update(const INotification& n) const
        {
            std::cout<<"???: TestObserver: update()!\n";
        }
        virtual void update(const ITimerNotification& n) const
        {
            std::cout<< n.getTime().tv_sec << "." << n.getTime().tv_usec <<": TestObserver: update()!\n";
        }
};

代码运行,CTimer::notify()被调用,创建TimerNotification并通过readNotification()将其传递给观察者,后者又调用通知的read()方法,最后调用观察者(希望)正确的update()方法。

最后一步是失败了。它调用update(INotification&)方法而不是所需的update(ITimerNotification&)方法。

我在这里尝试的Double Dispatch模式有什么用?它似乎没有获得正确的类型信息来选择适当的函数调用。

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

CTimerNotification需要这样的read

virtual void read(const IObserver& o) const {
    ITimerObserver* to = dynamic_cast<ITimerObserver*>(&o);
    if (to) {
        to->update(*this);
    } else {
        o.update(*this);
    }
}

您需要using IObserver::update;中的ITimerObserver