文章目录
一、Observer
1、优点
2、适用场景
3、模板示例
#include <iostream>
#include <vector>
class Subject;
/** 为对象定义一个更新接口,当主题发生变化时应通知该对象 */
class Observer
{
public:
virtual ~Observer() {}
virtual int getState() = 0;
virtual void update( Subject *subject ) = 0;
};
/** 存储对ConcreteObserver对象的状态,并在状态改变时发送一个通知给它的观察者 */
class ConcreteObserver : public Observer
{
public:
ConcreteObserver( const int state ) :
observer_state( state ) {}
~ConcreteObserver() {}
int getState() { return observer_state; }
void update( Subject *subject );
private:
int observer_state;
};
/** 了解它的观察者,并提供一个接口来附加和分离观察者 */
class Subject
{
public:
virtual ~Subject() {}
/* 添加观察者 */
void attach( Observer *observer );
/* 删除观察者 */
void detach( const int index );
/* 通知 */
void notify()
{
for ( unsigned int i = 0; i < observers.size(); i++ )
{
observers.at( i )->update( this );
}
}
virtual int getState() = 0;
private:
std::vector<Observer*> observers;
};
/** 存储状态应该与主题保持一致 */
class ConcreteSubject : public Subject
{
public:
~ConcreteSubject() {}
int getState() { return subject_state; }
void setState( const int s ) { subject_state = s; }
private:
int subject_state;
};
void ConcreteObserver::update( Subject *subject )
{
observer_state = subject->getState();
std::cout << "Observer state updated." << std::endl;
}
int main()
{
ConcreteObserver observer1( 1 );
ConcreteObserver observer2( 2 );
std::cout << "Observer 1 state: " << observer1.getState() << std::endl;
std::cout << "Observer 2 state: " << observer2.getState() << std::endl;
Subject *subject = new ConcreteSubject();
subject->attach( &observer1 );
subject->attach( &observer2 );
subject->setState( 10 );
subject->notify();
std::cout << "Observer 1 state: " << observer1.getState() << std::endl;
std::cout << "Observer 2 state: " << observer2.getState() << std::endl;
delete subject;
return 0;
}
4、实例
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 << ".";
}
};
class IProgress{
public:
virtual void DoProgress(float value)=0;
virtual ~IProgress(){}
};
class FileSplitter
{
string m_filePath;
int m_fileNumber;
List<IProgress*> m_iprogressList; // 抽象通知机制,支持多个观察者
public:
FileSplitter(const string& filePath, int fileNumber) :
m_filePath(filePath),
m_fileNumber(fileNumber){s
}
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.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++;
}
}
};