设计模式-观察者模式

动机:

在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密, 将使软件不能很好地抵御变化。

使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合

案例:

案例:文件分割器,在界面上显示分割进度

C++中尽量不要多继承,因为会有很多问题。但是可以继承一个主基类,然后再继承多个接口,这样一般是没问题的

抽象:将“通知依赖”关系抽象为1个接口,比如案例中splitter就是被观察者,界面窗口(进度条)、控制台就是观察者

如何支持多个观察者:vector

要点总结:

使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。

目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。

观察者自己决定是否需要订阅通知,目标对象对此一无所知。

Observer模式是基于事件的UI框架中非常常用的设计模式,也是 MVC模式的一个重要组成部分。

https://github.com/zhtsmailbox/design-patterns-cpp/blob/master/docs/Observer.md

/*
 * C++ Design Patterns: Bridge
 * Author: Jakub Vojvoda [github.com/JakubVojvoda]
 * 2016
 *
 * Source code is licensed under MIT License
 * (for more details see LICENSE)
 *
 */

#include <iostream>
#include <vector>

class Subject;

/*
 * Observer
 * defines an updating interface for objects that should be notified
 * of changes in a subject
 */
class Observer
{
public:
  virtual ~Observer() {}
  
  virtual int getState() = 0;
  virtual void update( Subject *subject ) = 0;
  // ...
};

/*
 * Concrete Observer
 * stores state of interest to ConcreteObserver objects and
 * sends a notification to its observers when its state changes
 */
class ConcreteObserver : public Observer
{
public:
  ConcreteObserver( const int state ) :
    observer_state( state ) {}
  
  ~ConcreteObserver() {}
  
  int getState()
  {
    return observer_state;
  }
  
  void update( Subject *subject );
  // ...

private:
  int observer_state;
  // ...
};

/*
 * Subject
 * knows its observers and provides an interface for attaching
 * and detaching observers
 */
class Subject
{
public:
  virtual ~Subject() {}
  
  void attach( Observer *observer )
  {
    observers.push_back(observer);
  }
  
  void detach( const int index )
  {
    observers.erase( observers.begin() + index );
  }
  
  void notify()
  {
    for ( unsigned int i = 0; i < observers.size(); i++ )
    {
      observers.at( i )->update( this );
    }
  }
  
  virtual int getState() = 0;
  virtual void setState( const int s ) = 0;
  // ...

private:
  std::vector<Observer*> observers;
  // ...
};

/*
 * Concrete Subject
 * stores state that should stay consistent with the subject's
 */
class ConcreteSubject : public Subject
{
public:
  ~ConcreteSubject() {}
  
  int getState()
  {
    return subject_state;
  }
  
  void setState( const int s )
  {
    subject_state = s;
  }
  // ...
  
private:
  int subject_state;
  // ...
};

void ConcreteObserver::update( Subject *subject )
{
  observer_state = subject->getState();
  std::cout << "Observer state updated." << std::endl;
}


int main()
{
  ConcreteObserver observer1( 1 );
  ConcreteObserver observer2( 2 );
  
  std::cout << "Observer 1 state: " << observer1.getState() << std::endl;
  std::cout << "Observer 2 state: " << observer2.getState() << std::endl;
  
  Subject *subject = new ConcreteSubject();
  subject->attach( &observer1 );
  subject->attach( &observer2 );
  
  subject->setState( 10 );
  subject->notify();
  
  std::cout << "Observer 1 state: " << observer1.getState() << std::endl;
  std::cout << "Observer 2 state: " << observer2.getState() << std::endl;
  
  delete subject;
  return 0;
}