0
点赞
收藏
分享

微信扫一扫

C++【设计模式】 | 【03 组件协作模式】Observer

文章目录

一、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++;
		}
	}
};
举报

相关推荐

0 条评论