Observer设计模式

Observer/Event

动机(Motivation)

  • 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。
  • 使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合

模式定义

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

例子

传输大文件将其分割成多个小文件。之后添加进度条功能。

不好的设计

设计

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 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 IProgress{ // 表达通知抽象
public:
	virtual void DoProgress(float value)=0; // 更新
	virtual ~IProgress(){}
};


class FileSplitter
{
	string m_filePath;
	int m_fileNumber;

	// ProgressBar* m_progressBar; // 具体的通知控件
	// Iprogress* iprogress; // 通知抽象机制
	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.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++;
		}
	}
};
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 << ".";
	}
};


要点总结

  • 使用面向对象的抽象,Observer模式使得我们可以独立地改变目标与观察者,从而使二者之间的依赖关系达致松耦合。
  • 目标发送通知时,无需指定观察者,通知(可以携带通知信息作为参数)会自动传播。
  • 观察者自己决定是否需要订阅通知,目标对象对此一无所知。
  • Observer模式是基于事件的UI框架中非常常用的设计模式,也是MVC模式的一个重要组成部分。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下是一个使用观察者(Observer设计模式的示例代码(C++): ```cpp #include <iostream> #include <vector> // 观察者接口 class Observer { public: virtual void update(const std::string& message) = 0; }; // 具体观察者A class ConcreteObserverA : public Observer { public: void update(const std::string& message) override { std::cout << "具体观察者A收到消息:" << message << std::endl; } }; // 具体观察者B class ConcreteObserverB : public Observer { public: void update(const std::string& message) override { std::cout << "具体观察者B收到消息:" << message << std::endl; } }; // 被观察者(主题)类 class Subject { private: std::vector<Observer*> observers; std::string message; public: void attach(Observer* observer) { observers.push_back(observer); } void detach(Observer* observer) { for (auto it = observers.begin(); it != observers.end(); ++it) { if (*it == observer) { observers.erase(it); break; } } } void notify() { for (auto observer : observers) { observer->update(message); } } void setMessage(const std::string& newMessage) { message = newMessage; notify(); } }; // 客户端代码 int main() { // 创建具体观察者对象 Observer* observerA = new ConcreteObserverA(); Observer* observerB = new ConcreteObserverB(); // 创建被观察者对象 Subject subject; // 注册观察者 subject.attach(observerA); subject.attach(observerB); // 设置消息并通知观察者 subject.setMessage("Hello World!"); // 取消注册观察者B subject.detach(observerB); // 设置新消息并通知观察者 subject.setMessage("Goodbye!"); delete observerA; delete observerB; return 0; } ``` 在上述示例代码中,我们定义了一个观察者接口 `Observer`,并要求具体的观察者类继承并实现该接口。具体的观察者类 `ConcreteObserverA` 和 `ConcreteObserverB` 分别定义了不同的更新行为。 被观察者(主题)类 `Subject` 包含一个观察者列表,并提供了注册、注销和通知观察者的方法。通过调用 `notify()` 方法,被观察者会遍历观察者列表,并调用每个观察者的 `update()` 方法来传递消息。 在客户端代码中,我们创建了具体的观察者对象,并将它们注册到被观察者中。然后,通过设置消息并调用被观察者的 `setMessage()` 方法来通知观察者。在示例中,我们设置了两条消息,并在第二条消息后注销了一个观察者。 运行代码将输出每个观察者收到的消息。 这个示例展示了观察者设计模式的基本结构和使用方式,并在 C++ 中实现了它。通过使用观察者模式,可以实现对象之间的松耦合,当一个对象的状态发生变化时,它的所有观察者都会得到通知并进行相应的处理。记得在程序结束时删除动态分配的内存。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

量子孤岛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值