“组件协作”模式:
>现代软件专业分工之后的第一个结果是“框架与应用程序的划分”
“组件协作”模式通过晚期绑定,来实现框架与应用程序之间的松耦合,是二者之间协作时常用的模式。
>典型模式
. Template Method
. Strategy
. Observer/ Event
例:
在一个窗口中添加进度条
普通的做法:
MainForm.cpp
class MainForm :public Form { TextBox* txtFilePath; TextBox* txtFileNumber; //最朴素的做法,就是增添 ProgressBar* progressBar; //依赖项 依赖倒置原则 public: void Button1_Click(){ string filePath = txtFilePath->getText(); int number = atoi(txtFileNumber->getText().c_str()); FileSplitter splitter(filePath, number, progressBar); splitter.split(); } };
FileSplitter.cpp
class FileSplitter { string m_filePath; int m_fileNumber; //改动 ProgressBar* m_progressBar; public: FileSplitter(const string& filePath, int fileNumberm, ProgressBar* progressBar) : //通过构造器给参数赋值 m_filePath(filePath), m_fileNumber(fileNumber), m_progressBar(progressBar){ } void split(){ //1.读取大文件 //2.分批次向小文件中写入 for (int i = 0; i < m_fileNumber; i++){ //.... //改动 if (m_progressBar != null) { m_progressBar->setValue((i + 1) / m_fileNumber); //更新进度条 } } } };
此方法将出现的问题:
如果出现问题,首先要想到的是八大原则:
该方法首先违背“依赖倒置原则”,该原则为“不要依赖A,而是依赖A的抽象”
观察者模式的做法:
MainForm.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()); FileSplitter splitter(filePath, number, progressBar); splitter.split(); } virtual void DoProgress(float value){ progressBar->setValue(value); } };
FileSplitter.cpp
class IProgress{ public: virtual void DoProgress(float value) = 0; virtual ~IProgress(){} }; class FileSplitter { string m_filePath; int m_fileNumber; //ProgressBar* progressBar; //具体通知控件 IProgress* m_iprogress; //抽象通知机制 public: FileSplitter(const string& filePath, int fileNumber, IProgress* iprogress) : //通过构造器给参数赋值 m_filePath(filePath), m_fileNumber(fileNumber), m_iprogress(iprogress){ } void split(){ //1.读取大文件 //2.分批次向小文件中写入 for (int i = 0; i < m_fileNumber; i++){ //.... if (m_iprogress != nullptr) { float progressValue = m_fileNumber; progressValue = (i + 1) / progressValue; m_iprogress->DoProgress(progressValue); //更新进度条 } } } };
总结:
使用面向对象的抽象, Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。
目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。
观察者自己决定是否需要订阅通知,目标对象对此一无所知。
Observer模式是基于事件的UI框架中非常常用的设计模式,也是MVC模式的一个重要组成部分。