观察者模式

来源:互联网 发布:淘宝里有家小崔韩代 编辑:程序博客网 时间:2024/06/05 20:29

观察者模式

 

观察者模式是最常用的设计模式之一。观察者模式定义了一种一对多的关系,多个观察者同时监听一个主题对象,当主题对象改变的时候会通知所有观察者对象,被通知的观察者会自动更新。

 

经典的观察者模式:

 

class Observer;

 

// 主题对象

class Observable

{

public:

     virtual ~Observable() {}

 

     virtual void registerObserver(Observer* o);

     virtual void unregisterObserver(Observer* o);

     // 通知所有观察者

     virtual void notifyObservers();

 

private:

     list<Observer*> observers; // 观察者列表

};

 

// 观察者

class Observer

{

public:

     virtual ~Observer() {}

 

     virtual void update() = 0; // 收到通知后的动作

};

 

inline void Observable::registerObserver(Observer* o)

{

     observers.push_back(o);

}

 

inline void Observable::unregisterObserver(Observer* o)

{

     observers.remove(o);

}

 

Observable是主题对象,也就是被观察者,子类只要继承就可以了。Observable保存一个观察者(Observer列表。主题首先调用registerObserver方法将一个观察者对象注册到观察者列表中。当主题对象状态改变并且需要通知观察者时,就调用notifyObservers方法通知所有观察者更新主题状态。当主题需要解除观察者的依赖时,调用unregisterObserver方法。

    Observer观察者对象,定义了一个update的纯虚函数,子类需要继承并实现这个函数。update是观察者的一个回调函数,主题状态发生改变通知观察者正是调用了这个函数。

    ObservableObserver具有一定的耦合,通过通知-回调机制,在具体的使用过程中可以将耦合性降到最低。

 

struct A : public Observable

{

     A (int i) : i_(i) {}

 

     int i_;

};

 

struct B : public Observer

{

     int i_;

 

     B(boost::shared_ptr<A>& a) : a_(a)

     {

         a->registerObserver(this);

         i_ = a->i_;

     }

 

     virtual void update()

     {

         if (a_ != NULL)

         {

              i_ = a_->i_;

         }

     }

 

private:

     boost::shared_ptr<A> a_;

};

 

void test()

{

     boost::shared_ptr<A> a(new A(10));

     boost::shared_ptr<B> b(new B(a));

 

     cout << b->i_ << endl;

     a->i_ = 100;

     a->notifyObservers();

 

     cout << b->i_ << endl;

}

 

输出:

10

100

   

这个观察者模式存在一些不足,上面也提到过,观察者模式中主题和观察者具有一定的耦合性,也就是说一个对象的改变会影响另一个依赖的对象。例如,主题并不能确定每个观察者的指针是否有效,假如其中一些观察者在程序运行的过程中已经被释放了,调用到这些已经被释放的指针时,程序就会崩溃。代码如下:

 

void test()

{

     boost::shared_ptr<A> a(new A(10));

     B* b = new B(a);

     delete b;

 

     a->i_ = 100;

     a->notifyObservers(); // 这里发生程序崩溃

}

 

       因此使用的过程中需要有效的管理主题对象和观察者对象的生命期。

原创粉丝点击