大文件分割,使用各种状态观察分割的进度。
一、普通写法
// 算法文件
// 滑动条,显示文件分割的进度
class ProgressBar{
public:
void SetValue(float val){
}
};
// 文件分割器
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 Form{
};
class TextBox{
public:
string getText(){
return "";
}
};
class MainForm : public Form{
TextBox* txtFilePath;
TextBox* txtFileNumber;
ProgressBar* progressBar;
public:
void Button_Click(){ // 左键单击
string filePath = txtFilePath->getText();
int number = atoi(txtFileNumber->getText().c_str());
FileSplitter spliter(filePath,number,progressBar);
spliter.Split();
}
};
二、观察者模式
// 文件分割器算法
#include <iostream>
#include <string>
#include <list>
using namespace std;
// 封装分割部分
// 抽象观察者
class IProgress{
public:
virtual void DoProgress(float value) = 0;
virtual ~IProgress(){}
};
// 具体文件切割类
class FileSpliter{
string m_filePath;
int m_fileNumber;
list<IProgress*> m_iProgressList; // 抽象通知机制,支持多个观察者
public:
FileSpliter(const string& filePath,int fileNumber) :
m_filePath(filePath),
m_fileNumber(fileNumber){
}
void Splist(){
// 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.push_back(iprogress);
}
// 移除观察者
void removeIProgress(IProgress* iprogress){
m_iProgressList.remove(iprogress);
}
protected:
virtual void onProgress(float value){
list<IProgress*>::iterator itor = m_iProgressList.begin();
while(itor != m_iProgressList.end()){
(*itor)->DoProgress(value); // 更新进度条,等观察者
itor++;
}
}
};
// 文件分割器主程序,可以支持多个观察者
#include "Observer.cpp"
// 滑动条,显示文件分割的进度
class ProgressBar{
public:
void SetValue(float val){
}
};
// 界面文件
class Form{
};
class TextBox{
public:
string getText(){
return "2";
}
};
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 Button_Click(){
string filePath = txtFilePath->getText();
int number = atoi(txtFileNumber->getText().c_str());
ConsoleNotifier cn;
FileSpliter spliter(filePath,number);
spliter.addIProgress(this);
spliter.addIProgress(&cn);
spliter.Splist();
}
virtual void DoProgress(float value){
progressBar->SetValue(value);
}
};
int main(){
return 0;
}
观察者模式的动机:
在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。
使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。
观察者模式定义:
定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的装填发生改变时,所有依赖于它的对象都得到通知并自动更新。 ——《设计模式》GoF
总结:
使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使两者之间的依赖关系达到松耦合。
目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。
观察者自己决定是否需要订阅通知,目标对象对此一无所知。
观察者模式是基于事件的UI框架中非常常用的设计模式,也是MVC模式的一个重要组成部分。