c++ - 观察者模式中的 Const-correct 通知程序

标签 c++ constants observer-pattern const-correctness

我想实现一个不改变模型的模型类的观察者。因此,它应该能够使用常量引用来访问模型。但是观察员的注册禁止这样做。

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



//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++ 无法区分并将状态和观察者混为一谈,强制两者为常量或非常量。

干杯,菲利克斯

最佳答案

如果您认为通知程序对象不是拥有它的模型对象的一部分,因此修改通知程序不会“算作”修改模型,那么让 getNotifier 成为返回非常量引用的常量方法:

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

     return m_Notifier; 
}

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

可能还有其他设计方法(例如 Vinay 添加了另一个类),但您的评论“是非常量,因为它需要返回非常量引用”向我表明您可以完全按照自己的意愿行事最初想要,只是你没有意识到你可以。

关于c++ - 观察者模式中的 Const-correct 通知程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/725375/

相关文章:

observer-pattern - Magento AddAttributeToSelect() 关于自定义添加的属性(观察者)

android - Android SQLite 数据库的 ContentObserver

c++ - 是否可以使用 d[x] 寄存器中的值作为 vld 中的地址?

c++ - 如何使用 Qt/C++ 获取 CPU 和主板序列号?

c++ - 在 const 方法中使用引用

c - "Initializer element is not constant"将对象定义为函数的静态成员时

c++ - 为什么 bitand 没有正确解析以形成右值引用?

c++ - XNextEvent 在应用程序开始时阻塞

c++ - 传递给函数的临时对象是否被视为 const?

design-patterns - 异步观察者模式