观察者模式
Model-View-Controller架构就是观察者模式的例子,C#中的Event委托也是使用的观察者模式
##### 进度条更新初阶版本 |
下面样例产生了编译时的依赖(违背了抽象依赖细节)应该依赖抽象基类(MainForm与ProgressBar之间产生了依赖)
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
| class FileSplitter { string m_filePath; int m_fileNumber; ProgressBar* m_progressBar;
public: FileSplitter(const string& filePath, int fileNumber, ProgressBar* progressBar) : m_filePath(filePath), m_fileNumber(fileNumber), m_progressBar(progressBar){
}
void split(){
//1.读取大文件
//2.分批次向小文件中写入 for (int i = 0; i < m_fileNumber; i++){ //... float progressValue = m_fileNumber; progressValue = (i + 1) / progressValue; //更新进度条 //不能依赖实现细节 m_progressBar->setValue(progressValue); } }
class MainForm : public Form { TextBox* txtFilePath; TextBox* txtFileNumber; //依赖ProgressBar ProgressBar* progressBar;
public: void Button1_Click(){
string filePath = txtFilePath->getText(); int number = atoi(txtFileNumber->getText().c_str());
FileSplitter splitter(filePath, number, progressBar);
splitter.split(); } };
|
|
文件读取进度条更新观察者模式改进版本
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
| //修改后,将progressbar抽象成接口,紧耦合变成松耦合,编译就不依赖progress //变成了良好的耦合,符合依赖倒置原则 //iprogress接口 class IProgress{ public: virtual void DoProgress(float value)=0; virtual ~IProgress(){} };
//被观察对象拥有一个观察者对象的集合(相当于subject) class FileSplitter { string m_filePath; int m_fileNumber; //改良:使支持多个观察者,加入vector 或者list等 List<IProgress*> m_iprogressList; // 抽象通知机制,支持多个观察者 public: FileSplitter(const string& filePath, int fileNumber) : m_filePath(filePath), m_fileNumber(fileNumber){ }
void split(){ //1.读取大文件 //2.分批次向小文件中写入 for (int i = 0; i < m_fileNumber; i++){ //... float progressValue = m_fileNumber; progressValue = (i + 1) / progressValue; onProgress(progressValue);//发送通知 } }
//原本列表初始化已经不适用,添加add和remove操作函数 void addIProgress(IProgress* iprogress){ m_iprogressList.push_back(iprogress); }
void removeIProgress(IProgress* iprogress){ m_iprogressList.remove(iprogress); }
//继续优化,protected下写onProgress,层次更清晰 protected: //对于onprogress也需要改变 virtual void onProgress(float value){ List<IProgress*>::iterator itor=m_iprogressList.begin(); while (itor != m_iprogressList.end() ) (*itor)->DoProgress(value); //更新进度条 itor++; } } };
|
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
| class ConsoleNotifier : public IProgress { public: virtual void DoProgress(float value){ cout << "."; } };
class MainForm : public Form, public IProgress { TextBox* txtFilePath; TextBox* txtFileNumber;
ProgressBar* progressBar;
public: void Button1_Click(){
string filePath = txtFilePath->getText(); int number = atoi(txtFileNumber->getText().c_str());
ConsoleNotifier cn;
FileSplitter splitter(filePath, number); //添加监听 splitter.addIProgress(this); //订阅通知 splitter.addIProgress(&cn); //订阅通知
splitter.split();
splitter.removeIProgress(this);
} //重写DoProgress virtual void DoProgress(float value){ progressBar->setValue(value); } };
|