动机

观察者模式意图建立一种对象间一对多的关系,当一个对象中的状态发生改变时,所有依赖它的对象都会收到通知并自动同步更新。

示例

试想这样一种场景,有一组数据,可以通过不同的图表的方式被展示,比如柱状图、折线图、饼状图等等。虽然展示的方式不同,但数据应该是同样的一组,假设这组数据有一个数据对象关系,那么这个数据对象的任何改变都应该及时地在展示它的图表对象中同步改变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
class Subject;

class Observer {
public:
virtual ~Observer() = default;

virtual void update(Subject* changedobj) = 0;

protected:
Observer() = default;
};

class Subject {
public:
virtual ~Subject() = default;

virtual void attach(Observer* observer) {
m_observers.push_front(observer);
}

virtual void notify() {
for(auto observer : m_observers) {
observer->update(this);
}
}

protected:
explicit Subject(const std::string& name) : m_name(name) { }

private:
std::list<Observer*> m_observers{};

public:
std::string m_name;
};

class Data : public Subject {
public:
explicit Data(const std::string& name) : Subject(name) { };

void change() {
notify();
}
};

class PieChart : public Observer {
public:
void update(Subject* changedobj) {
cout << changedobj->m_name << " changed, PieChart update\n";
}
};

class BarChart : public Observer {
public:
void update(Subject* changedobj) {
cout << changedobj->m_name << " changed, BarChart update\n";
}
};

class LineChart : public Observer {
public:
void update(Subject* changedobj) {
cout << changedobj->m_name << " changed, LineChart update\n";
}
};

int main() {
Data data("data");
PieChart pie;
BarChart bar;
LineChart line;
data.attach(&pie);
data.attach(&bar);
data.attach(&line);
data.change();

return 0;
}

这里分别有饼状图、柱状图和折线图来展示同一组数据,使用被观察者的绑定方法,将图表绑定到数据上,当数据更新时,调用通知方式,让所有相关的图表对象更新。
执行结果:

1
2
3
data changed, LineChart update
data changed, BarChart update
data changed, PieChart update