观察者模式中的正确通知程序

The*_*ger 2 c++ const const-correctness observer-pattern

我想实现一个Model类的Observer,它不会改变Model.因此,它应该能够使用const-Reference来访问Model.但注册观察员禁止这样做.

以下是我的项目中如何实现观察者模式:



//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();
    }

};

非修改观察者需要"更改"模型的唯一地方是它想要注册它.我觉得我无法在这里避免使用const_cast,但我想知道是否有更好的解决方案.

旁注:换句话说,我不认为模型对象设法成为模型状态的一部分的"观察者列表".C++无法区分并将状态和观察者结合在一起,迫使它们都是const或非const.

干杯,菲利克斯

Ste*_*sop 5

如果您认为Notifier对象不属于拥有它的Model对象的一部分,那么修改Notifier不会"计数"为修改Model,那么使getNotifier成为一个返回非const引用的const方法:

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

     return m_Notifier; 
}
Run Code Online (Sandbox Code Playgroud)

然后,您必须将m_Notifier标记为可变,或者通过指针(或智能指针)或引用而不是包含来拥有它.无论哪种方式,您都避免使用const_cast.通常最好嵌入对象而不是指向/引用它们,但如果这是Notifier不被认为是使用它的模型的一部分的情况,则嵌入不是必需的.通过引用拥有它会强制您在构造Model时初始化引用,这会导致依赖注入,这不是坏事.拥有智能指针意味着,与嵌入一样,您无需执行任何有关清理的操作.

可能还有其他设计方法(例如Vinay添加了另一个类),但你的评论"非const是因为它需要返回一个非const引用",这表明你可以完全按照你原来想要的那样做,你只是没有意识到你可以.