观察者模式中的Const-correct Notifier [英] Const-correct Notifier in Observer Pattern

查看:160
本文介绍了观察者模式中的Const-correct Notifier的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现一个不改变Model的Model类的Observer。因此,它应该能够使用const-Reference访问模型。



<$>这是观察者模式在我的项目中实现的方式:

 


//类型的属性Observable由要通知其他人的类使用状态更改的
//。观察对象使用AddObserver注册自身。
//必要时,Observable对象调用NotifyObservers。
class Notifier
{
public:
AddObserver(Observer *);
RemoveObserver(Observer *);
NotifyObservers();
};

类模型
{
public:
Notifier&GetNotifier()//是非常量,因为它需要返回一个非常量
{参考允许观察者注册自己。

return m_Notifier;
}

int QueryState()const;

void ChangeModel(int newState)
{
m_Notifier.NotifyObservers();
}

private:
通知程序m_Notifier;
};

//此视图不修改模型。
class MyNonModifingView:public Observer
{
public:
SetModel(Model * aModel)//应为const Model * aModel ...
{
m_Model = aModel;
m_Model-> GetNotifier()。AddObserver(this); //...but不能因为
// SetModel需要调用GetNotifier并添加自身,这需要
//非常量AddObserver和GetNotifier方法。
}

void Update()//由Notifiers调用的Observer接口的一部分
{
m_Model-> QueryState();
}

};

非修改观察者需要更改模型的唯一位置是当它想要注册它。我觉得我不能避免在这里的const_cast,但我想知道是否有更好的解决方案。



Sidenote:
换句话说,考虑模型对象管理为模型状态的一部分的观察者列表。



Cheers,Felix

div class =h2_lin>解决方案

如果你认为Notifier对象不是拥有它的Model对象的一部分,那么修改通知器不会修改然后使getNotifier成为返回非const引用的const方法:

 通知程序& GetNotifier()const //是const但是返回一个非const 
{//允许观察者到
//注册自己。

return m_Notifier;
}

然后您必须将m_Notifier标记为mutable,指针(或智能指针)或引用,而不是包含。无论如何,你避免const_cast。通常最好嵌入对象而不是点/引用它们,但如果这是一个Notifier不被认为是使用它的模型的一部分,那么嵌入不是必需的。通过引用拥有它会迫使您在构建模型时初始化引用,这将导致依赖注入,这不是坏事。拥有智能指针意味着,和嵌入一样,你不必做任何关于清理的事情。



可能有其他方法来设计事物另一个类),但你的评论是非常数,因为它需要返回一个非常量引用建议我,你可以做你真正想要的,你只是不知道你可以。


I want to implement an Observer of a Model class which does not change the Model. Thus, it should be able to use a const-Reference to access the Model. But the Registering of the Observer prohibits this.

Here is how the observer pattern is implemented in my Project:



//Attributes of type Observable are used by classes that want to notify others
//of state changes. Observing Objects register themselves with AddObserver.
//The Observable Object calls NotifyObservers when necessary.
class Notifier
{
public:
    AddObserver(Observer*);
    RemoveObserver(Observer*);
    NotifyObservers();
};

class Model
{
public:
    Notifier& GetNotifier() //Is non const because it needs to return a non-const 
    {                       //reference to allow Observers to register themselves.

         return m_Notifier; 
    }

    int QueryState() const;

    void ChangeModel(int newState)
    {
        m_Notifier.NotifyObservers();
    }

private:
    Notifier m_Notifier;
};

//This View does not Modify the Model.
class MyNonModifingView : public Observer
{
public:
    SetModel(Model* aModel)  //should be const Model* aModel...
    {
        m_Model = aModel;
        m_Model->GetNotifier().AddObserver(this); //...but can't because
        //SetModel needs to call GetNotifier and add itself, which requires
        //non-const AddObserver and GetNotifier methods.
    }

    void Update()  //Part of Observer-Interface, called by Notifiers
    {
        m_Model->QueryState();
    }

};

The only place where a non-modifying observer needs to "change" the Model is when it wants to register with it. I feel that I can not avoid a const_cast here, but I wanted to know if there are better solutions.

Sidenote: Put another way, I don't consider the "List of Observers" which a model object manages to be part of the state of the Model. C++ can not tell the difference and lumps state and observers together, forcing both to be const or non-const.

Cheers, Felix

解决方案

If you consider the Notifier object not to be part of the Model object which owns it, so that modifying the Notifier doesn't "count" as modifying the Model, then make getNotifier a const method returning a non-const reference:

Notifier& GetNotifier() const //Is const but returns a non-const 
{                             //reference to allow Observers to 
                              //register themselves.

     return m_Notifier; 
}

You will then have to either mark m_Notifier as mutable, or else own it by pointer (or smart pointer) or reference rather than by inclusion. Either way, you avoid a const_cast. It is usually preferable to embed objects rather than point/refer to them, but if this is a case where a Notifier isn't considered part of the Model which uses it, then embedding is not essential. Owning it by reference forces you to initialize the reference when Model is constructed, which leads to dependency injection, which is no bad thing. Owning by smart pointer means that, as with embedding, you don't have to do anything about cleanup.

There may be other ways to design things (such as Vinay's addition of another class), but your comment "Is non-const because it needs to return a non-const reference" suggests to me that you can do exactly what you originally wanted, you just don't realise you can.

这篇关于观察者模式中的Const-correct Notifier的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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