观察者模式
- 观察者模式(Observe)
动机
在软件构建过程中,我们需要为某些对象建立一种 (通知依赖关系)
—— 一个对象 ***(目标对象)*** 的状态发生改变,所有的依赖对象 ***(观察者对象)*** 都将得到通知。如果这样的依赖关系过于紧密,将使得软件不能很好的抵御变化使用面向对象技术,可以将这种依赖弱化,并形成一定稳定的依赖关系。从而实现软件体系结构的松耦合
例子
创建一个进度条的更新程序,程序的作用是将一个大文件进行分割
1 | class MainForm : public Form{ |
问题
- 违背设计的原则
- 依赖倒置原则,
- 高层模块不应该依赖底层模块,二者都应该依赖于抽象。
- 抽象不应该依赖于实现细节,实现细节应该依赖抽象
- 依赖倒置原则,
直观改进
应该依赖于实现的父类
父类可能没有相应的更新方法
改进(通知单个对象)
我们需要的是告诉控件需要发生变化。因此抽象为一个通知
cpp支持多继承,但不推荐。推荐一个主继承类,其他继承接口
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
62class IProcess{
public:
virtual void DoProgress(float val)=0;
virtual ~IProcess();
}
class MainForm : public Form,public IProcess{
TextBox* txtFilePath;
TextBox* textFileNumber;
public: Button_click(){
string filePath = txtFilePath->getText();
int number = atoi(textFileNumber->getText().c_str());
// ProgessBar m_progressBar; //具体的通知控件
ProcessBar* processBar; // 抽象通知机制
FileSplitter splitter(filePath,number,this);
splitter.split();
}
virtual void DoProgress(float val){
processBar->setValue(val);
}
}
class FileSplitter{
string m_filePath;
int m_fileNumber;
IProcess* m_iProcess;
public:
FileSplitter(const string& filePath,int fileNumber,IProcess* iProcess):
m_filePath(filePath),
m_fileNumber(fileNumber),
m_iProcess(iProcess){
}
void split(){
// 1.读取文件
// 2.分批次向小文件中写入
for(int i=0;i< m_fileNumber;i++){
//...
if(m_progressBar != nullptr){
onProgress((i+1)/m_fileNumber) //更新进度条
}
}
}
protected:
void onProgress(float value){
if(m_progressBar != nullptr){
m_progressBar->DoProgress(value);
}
}
}改进(多通知)
1 |
|
模式定义
定义对象间的一种 (一对多(变化)) 的依赖关系,以便当一个对象(Subject)的状态发生改变时,***(所有依赖于)*** 它的对象都能够得到通知