观察者模式 - 如何处理意外更改?

时间:2011-07-01 11:35:41

标签: design-patterns

使用什么样的机制来更新对象...除非我们不断检查它已经改变,然后指示主体/被观察者推动他的状态......

我的意思是例如一个对象改变状态,它应该如何处理这个改变,如果它只是将自己标记为已更改,但我如何让Observers知道它已经改变而不必总是检查对象是否我观察的情况有没有改变......我们如何处理意外的变化并将其从通知中删除?

有这整个回调的东西,事件监听器等...我使用但不太明白,我用它作为一个黑盒子,但我真的想知道更多关于这样的内部机制。

2 个答案:

答案 0 :(得分:2)

跟踪对象的变化有很多不同的机制。

第一种选择是使用确实观察者。这意味着每个更改对象数据的方法都会调用观察者。在实践中,最好将它放在一个函数中,如下所示:

class MyClass
   {
   public:
      void setValue(int value)
         {
         m_value = value;
         notifyObservers();
         }
   private:
      void notifyObservers()
         {
         for (auto it=m_observers.begin();it!=m_observers.end();++it)
            (*it)->notify(this);
         }
      std::list<Observer *> m_observers;
   };

另一种方法是存储对象是否已更改。但是,这要求您定义“已更改”的含义;换句话说:我何时重置'已更改'标志。 一个简单的解决方案是使用版本号。每当对象发生更改时,您都会增加版本号,如下所示:

class MyClass
   {
   public:
      void setValue(int value)
         {
         m_value = value;
         ++m_version;
         }
      int getVersion() const
         {
         return m_version;
         }
   private:
      int m_version;
   };

现在其他类可以简单地请求版本号并使用它来查看自上次询问版本号后它是否已被更改。

这两种方法都有其优点和缺点:

  • 在观察者机制中,更改可能很慢(因为您需要调用所有观察者),但您可以保证所有观察者都会立即进行更新
  • 在版本号方法中,更改非常快,但您依赖其他类来定期查询您的课程以进行更改

在您的情况下哪种机制最好取决于具体情况。如果发现在实践中最好混合它们,具体取决于具体情况。有些更改最好立即传播(例如在计算中),其他更改最好延迟(例如更新屏幕)。

答案 1 :(得分:1)

基本上Observer模式表示有一个对象是其他对象感兴趣的主题 比方说,我们有一个Kid对象,其中包含MathGradeGeographyGrade等属性。
现在,对象MotherFatherPrincipal都对Kid对象属性的更改感兴趣。
它们基本上有2个选项 -

  1. 每天都来Kid并问'你的MathGrade已经改变了吗?' '你的GeographyGrade改变了吗?'等
    这种方法效率不高。

  2. 他们只能对Kid说 - “好的,这是我的电话号码 - 如果您的MathGrade更改,请致电我。” 这本质上是观察者模式:对对象的更改感兴趣的人向该对象注册自己,并保证在发生更改时得到通知。

  3. 如果要返回编程世界,您将拥有一个IGradeObserver界面,该界面将声明MathGradeChanged(int newGrade)GeorgraphyGradeChanged(int newGrade)个功能。
    课程MotherFatherPrincipal将实施IGradeObserver 现在,Kid类将包含IGradeObserversRegisterObserver(IGradeObserver observer)方法的列表。

    现在,每当成绩发生变化时,Kid类将遍历其观察者列表,并通知他们该变化。

    回调和事件监听器是实现此模式的一种方式 我建议使用Google搜索,我自己找到了几个有趣的指南(herehere)。
    我相信你也可以找到其他一些,也与你选择的编程语言有关 祝好运。