-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathObserver-Pattern
152 lines (126 loc) · 4.69 KB
/
Observer-Pattern
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
2.观察者模式
定义:观察者是一种行为设计模式,在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新
原则:为交互对象之间的松耦合设计而努力。(主题只知道观察者实现了某个接口,不需要知道观察者的具体的类,做了些什么或其它细节)
针对接口编程,不针对实现编程
优点:
.解耦
被观察者和观察者之间建立一个抽象的耦合,被观察者无需知道具体观察者,所有观察者遵循一个共同抽象接口即可;符合“依赖倒转原则”原则。
.消息同步
观察者模式实现了“消息广播”功能。
缺点:
.通知消息延迟
被观察者对象如果存在较多的直接或者间接观察者,观察者收到的通知消息将会花费一定的时间。
.不支持循环依赖
如果观察者与被观察者之间存在循环依赖关系,被观察者会触发它们之间进行循环调用,导致系统崩溃。
.多线程调用隐患
如果被观察者的通知消息是通过另一线程异步发送的话,系统必须保证该发送过程是以“自恰”的方式进行。
实现:
抽象主题(Subject):跟踪所有观察者,并提供添加和删除观察者的接口。
抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题的通知时进行自我更新。
具体主题(ConcreteSubject):将有关状态存入各 ConcreteObserver 对象。当具体主题的状态发生任何更改时,通知所有观察者。
具体观察者(ConcreteObserver):实现 Observer 所要求的更新接口,以便使本身的状态与主题的状态相协调。
#include <iostream>
#include <list>
#include <string>
class IObserver {
public:
virtual ~IObserver(){};
virtual void Update() = 0;
};
class ISubject {
public:
virtual ~ISubject(){};
virtual void Attach(IObserver *observer) = 0;
virtual void Detach(IObserver *observer) = 0;
virtual void Notify() = 0;
};
/**
* The Subject owns some important state and notifies observers when the state
* changes.
*/
class Subject : public ISubject {
public:
virtual ~Subject() {
std::cout << "Goodbye, I was the Subject.\n";
}
/**
* The subscription management methods.
*/
void Attach(IObserver *observer) override {
list_observer_.push_back(observer);
}
void Detach(IObserver *observer) override {
list_observer_.remove(observer);
}
void Notify() override {
std::list<IObserver *>::iterator iterator = list_observer_.begin();
HowManyObserver();
while (iterator != list_observer_.end()) {
(*iterator)->Update();
++iterator;
}
}
void HowManyObserver() {
std::cout << "There are " << list_observer_.size() << " observers in the list.\n";
}
std::string GetState()
{
return message_;
}
void SetState(std::string message)
{
message_ = message;
Notify();
}
private:
std::list<IObserver *> list_observer_;
std::string message_;
};
class Observer : public IObserver
{
public:
Observer(Subject &subject) : subject_(subject) {
this->subject_.Attach(this);
std::cout << "Hi, I'm the Observer \"" << ++Observer::static_number_ << "\".\n";
this->number_ = Observer::static_number_;
}
virtual ~Observer() {
std::cout << "Goodbye, I was the Observer \"" << this->number_ << "\".\n";
RemoveMeFromTheList();
}
void Update() override {
message_from_subject_ = this->subject_.GetState();
PrintInfo();
}
void RemoveMeFromTheList() {
subject_.Detach(this);
std::cout << "Observer \"" << number_ << "\" removed from the list.\n";
}
void PrintInfo() {
std::cout << "Observer \"" << this->number_ << "\": a new message is available --> " << this->message_from_subject_ << "\n";
}
private:
std::string message_from_subject_;
Subject &subject_;
static int static_number_;
int number_;
};
int Observer::static_number_ = 0;
void ClientCode()
{
Subject *subject = new Subject;
Observer *observer1 = new Observer(*subject);
Observer *observer2 = new Observer(*subject);
Observer *observer3 = new Observer(*subject);
subject->SetState("Hello World! :D");
subject->SetState("The weather is hot today! :p");
subject->SetState("My new car is great! ;)");
delete observer3;
delete observer2;
delete observer1;
delete subject;
}
int main() {
ClientCode();
return 0;
}