Observer
动机
- 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密, 将使软件不能很好地抵御变化。
- 使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合
模式定义
定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
#include <iostream>
#include <vector>//或者List
class Subject; // 稳定的
class Observer // 稳定的
{
public:
virtual ~Observer() {}
virtual int getState() = 0;
virtual void update(Subject *subject) = 0;
// ...
};
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;
// ...
};
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;
// ...
};
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); // push_back
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;
}
/*
Observer 1 state: 1
Observer 2 state: 2
Observer state updated.
Observer state updated.
Observer 1 state: 10
Observer 2 state: 10
*/
使用场景
- 当抽象有两个方面,一个依赖于另一个方面
- 当对一个对象的更改需要更改其他对象,而你不知道需要更改多少个对象时
- 当一个对象应该能够通知其他对象而不假设这些对象是谁时
总结
- 使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。
- 目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。
- 观察者自己决定是否需要订阅通知,目标对象对此一无所知。
- Observer模式是基于事件的UI框架中非常常用的设计模式,也是 MVC模式的一个重要组成部分。