观察者模式
在软件实现过程中,一个对象的状态发生改变所依赖的对象都须得到通知需要通知,但这种依赖不能过于紧密,需要抵御变化,
通过实现进度条的伪码来实现
该MainForm1.cpp中通过实现具体的进度条代码,来达到需求,如果需求改变,则需要在源码中所需位置依次增加所需代码
MainForm1.cpp
1 class MainForm : public Form 2 { 3 TextBox* txtFilePath; 4 TextBox* txtFileNumber; 5 ProgressBar* progressBar; 6 7 public: 8 void Button1_Click(){ 9 10 string filePath = txtFilePath->getText(); 11 int number = atoi(txtFileNumber->getText().c_str()); 12 13 FileSplitter splitter(filePath, number, progressBar); 14 15 splitter.split(); 16 17 } 18 };
FileSplitter1.cpp
1 class FileSplitter 2 { 3 string m_filePath; 4 int m_fileNumber; 5 ProgressBar* m_progressBar; 6 7 public: 8 FileSplitter(const string& filePath, int fileNumber, ProgressBar* progressBar) : 9 m_filePath(filePath), 10 m_fileNumber(fileNumber), 11 m_progressBar(progressBar){ 12 13 } 14 15 void split(){ 16 17 //1.读取大文件 18 19 //2.分批次向小文件中写入 20 for (int i = 0; i < m_fileNumber; i++){ 21 //... 22 float progressValue = m_fileNumber; 23 progressValue = (i + 1) / progressValue; 24 m_progressBar->setValue(progressValue); 25 } 26 27 } 28 };
MainForm2.cpp
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); } virtual void DoProgress(float value){ progressBar->setValue(value); } }; class ConsoleNotifier : public IProgress { public: virtual void DoProgress(float value){ cout << "."; } };
通过在父类中声明一个纯虚函数,以指针的形式实现多态可以通过不同的数据结构实现多个通知,可根据各种不同需求在子类中(DoProgress())中实现具体的功能。
FileSplitter2.cpp
1 class IProgress{ 2 public: 3 virtual void DoProgress(float value)=0; 4 virtual ~IProgress(){} 5 }; 6 7 8 class FileSplitter 9 { 10 string m_filePath; 11 int m_fileNumber; 12 13 List<IProgress*> m_iprogressList; // 抽象通知机制,支持多个观察者 14 15 public: 16 FileSplitter(const string& filePath, int fileNumber) : 17 m_filePath(filePath), 18 m_fileNumber(fileNumber){ 19 20 } 21 22 23 void split(){ 24 25 //1.读取大文件 26 27 //2.分批次向小文件中写入 28 for (int i = 0; i < m_fileNumber; i++){ 29 //... 30 31 float progressValue = m_fileNumber; 32 progressValue = (i + 1) / progressValue; 33 onProgress(progressValue);//发送通知 34 } 35 36 } 37 38 39 void addIProgress(IProgress* iprogress){ 40 m_iprogressList.push_back(iprogress); 41 } 42 43 void removeIProgress(IProgress* iprogress){ 44 m_iprogressList.remove(iprogress); 45 } 46 47 48 protected: 49 virtual void onProgress(float value){ 50 51 List<IProgress*>::iterator itor=m_iprogressList.begin(); 52 53 while (itor != m_iprogressList.end() ) 54 (*itor)->DoProgress(value); //更新进度条 55 itor++; 56 } 57 } 58 };
单继承一个父类,多继承其他接口
不推荐大括号换行,这个增加了语法分析时间复杂度,扫描时要去掉回车换行符