设计模式-观察者模式

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();
}
};

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++){
//...
if (m_progressBar != nullptr){
progressBar->setValue( (i + 1) / m_fileNumber); // 更新进度条
}
}
}
};

违背了依赖倒置设计原则


class IProgress{
public:
virtual void DoProgress(float value) = 0;
virtual ~IProgress(){}
};

class FileSplitter{
string m_filePath;
int m_fileNumber;
//ProgressBar* m_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++){
//...
float progressValue = m_fileNumber;
progressValue = (i + 1) / progressValue;
onProgress(progressValue);
}
}
protected:
virtual void onProgress(float value){
if (m_iprogress != nullptr){
m_iprogress->DoProgress(progressValue); // 更新进度条
}
}
};

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, this);
splitter.split();
}
virtual void DoProgress(float value) {
progressBar->setValue(value);
}
};

此时FileSplitter没有耦合任何一个界面类,就可以独立编译,在哪里都能支持进度通知。

但仍存在问题:不好支持多个通知。

要支持多个观察者,现在只支持一个观察者(MainForm或ProgressBar)。


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 {
virtual void DoProgress(float value) {
cout << "." <<;
}
};

class FileSplitter{
string m_filePath;
int m_fileNumber;
//ProgressBar* m_progressBar; // 具体通知控件
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);
}
}
void addIProgress(IProgress* iprogress){
m_iprogressList.add(iprogress);
}
void removeIProgress(IProgress* iprogress){
m_iprogressList.remove(iprogress);
}
protected:
virtual void onProgress(float value){
List<IProgress*>::iterator it = m_iprogressList.begin();
while(it != m_iprogressList.end() ){
(*it)->DoProgress(value); // 更新进度条
it++;
}
}
};


定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。------《设计模式》GoF



Observer:IProgress Update:DoProgress Attach:addIProgress Detach:removeIProgress Notify:onProgress ConcreteSubject:FileSplitter
ConcreteObserver:MainForm和ConsoleNotifier
Observer和Subject是稳定的。下面具体的是变化的。


使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。

目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。

观察者自己决定是否需要订阅通知,目标对象对此一无所知。

Observer模式是基于事件的UI框架中非常常用的设计模式,也是MVC模式的一个重要组成部分。

相关推荐
哆啦A梦的口袋呀2 小时前
基于Python学习《Head First设计模式》第六章 命令模式
python·学习·设计模式
半路下车3 小时前
【Harmony OS 5】HarmonyOS应用测试指南
设计模式·harmonyos
周某某~3 小时前
一.设计模式的基本概念
设计模式
on the way 1234 小时前
行为型设计模式之Interpreter(解释器)
设计模式
cui_hao_nan4 小时前
设计模式——模板方法
java·设计模式
在未来等你4 小时前
Java并发编程实战 Day 11:并发设计模式
java·设计模式·多线程·并发编程·threadlocal·生产者消费者·读写锁
牛奶咖啡135 小时前
学习设计模式《十二》——命令模式
学习·设计模式·命令模式·队列请求·宏命令·可撤销恢复操作·参数化配置
哆啦A梦的口袋呀6 小时前
基于Python学习《Head First设计模式》第七章 适配器和外观模式
python·学习·设计模式
何中应6 小时前
【设计模式-5】设计模式的总结
java·后端·设计模式
季鸢15 小时前
Java设计模式之状态模式详解
java·设计模式·状态模式