ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

观察者模式

2022-09-13 22:35:04  阅读:223  来源: 互联网

标签:string observer void 观察者 模式 observers subjectState


理论

观察者模式,定义了一对多得依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。观察者模式又叫做发布-订阅(Publish/Subscribe)模式。

观察者模式的特点:

将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。而观察者模式的关键对象是主题 Subject 和观察者 Observer,一个 Subject 可以有任意数目的依赖它的Observer,一旦 Subject 的状态发生了改变,所有的 Observer 都可以得到通知。Subject 发出通知时并不需要知道谁是它的观察者,而任何一个具体观察者也不需要知道其他观察者的存在。

观察者模式的应用场景:

  1. 当一个对象的改变需要同时改变其他对象的时候,而且它不知道具有多少对象有待改变时。

  2. 当一个抽象模型有两个方面,其中一方面依赖另一方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。

观察者模式所做地工作其实就是在解除耦合。让耦合的双方都依赖抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。

实例

公司同事上班摸鱼,想让前台帮忙在老板回来的时候打电话通知他们

初步实现:双向耦合

//前台(通知者)发现老板回来,通知同事(观察者)不要摸鱼(状态)
#include <iostream>
#include <list>
using namespace std;

class Observer; //前向引用说明

//通知者类
class Subject {
public:
	//增加观察者
	void Attach(Observer* observer) {
		observers.push_back(observer);
	}

	//移除观察者
	void Detach(Observer* observer) {
		observers.remove(observer);
	}

	//通知
	void Notify();

	//状态
	string SubjectState(string subjectState) {
		this->subjectState = subjectState;
		return subjectState;
	}

private:
	list<Observer*> observers; //观察者列表
	string subjectState;
};

//观察者类
class Observer {
public:
	Observer(string name, Subject* _subject) {
		this->Name = name;
		this->subject = _subject;
	}

	//采取行动
	void Update(string subjectState) {
		this->observerState = subject->SubjectState(subjectState);
		cout << "观察者:" << this->Name << " 状态:" << this->observerState << " 停止摸鱼" << endl;
	}

private:
	string Name;
	string observerState;
	Subject* subject;
};

void Subject::Notify() {
	for (list<Observer*>::iterator it = observers.begin(); it != observers.end(); it++) {
		(*it)->Update(subjectState);
	}
}

//客户端
int main() {
	//创建一个通知者
	Subject* secretory = new Subject();

	//增加观察者
	secretory->Attach(new Observer("小张", secretory));
	secretory->Attach(new Observer("小王", secretory));

	//发现老板,改变状态
	secretory->SubjectState("老板回来了!");
	//通知观察者改变状态
	secretory->Notify();

	system("pause");
	return 0;
}

解耦实现一

#include <iostream>
#include <list>
using namespace std;

class Subject;

//抽象观察者类
class AbstractObserver {
public:
	virtual void Update(string subjectState) = 0;
};

//通知者类
class Subject {
public:
	//针对抽象编程,减少了与具体类之间的耦合
	void Attach(AbstractObserver* observer) {
		observers.push_back(observer);
	}

	void Detach(AbstractObserver* observer) {
		observers.remove(observer);
	}

	void Notify() {
		for (list<AbstractObserver*>::iterator it = observers.begin(); it != observers.end(); it++) {
			(*it)->Update(subjectState);
		}
	}

	string SubjectState(string subjectState) {
		this->subjectState = subjectState;
		return subjectState;
	}

private:
	list<AbstractObserver*> observers;
	string subjectState;
};

//具体观察者类
class Observer1 : public AbstractObserver {
public:
	Observer1(string name, Subject* _subject) {
		Name = name;
		subject = _subject;
	}
	void Update(string subjectState) {
		this->observerState = subject->SubjectState(subjectState);
		cout << "观察者:" << this->Name << " 状态:" << this->observerState << " 停止打游戏" << endl;
	}

private:
	string Name;
	string observerState;
	Subject* subject;
};

class Observer2 : public AbstractObserver {
public:
	Observer2(string name, Subject* _subject) {
		Name = name;
		subject = _subject;
	}
	void Update(string subjectState) {
		this->observerState = subject->SubjectState(subjectState);
		cout << "观察者:" << this->Name << " 状态:" << this->observerState << " 停止刷视频" << endl;
	}

private:
	string Name;
	string observerState;
	Subject* subject;
};

//客户端
int main() {
	Subject* secretory = new Subject();

	secretory->Attach(new Observer1("小张", secretory));
	secretory->Attach(new Observer2("小王", secretory));

	secretory->SubjectState("老板回来了!");
	secretory->Notify();

	system("pause");
	return 0;
}

解耦实现二:观察者模式

UML类图

 代码实现

#include <iostream>
#include <list>
using namespace std;

//抽象观察者类
class AbstractObserver {
public:
	virtual void Update(string subjectState) = 0;
};

//抽象通知者类
class AbstractSubject {
public:
	virtual void Attach(AbstractObserver* observer) = 0;
	virtual void Detach(AbstractObserver* observer) = 0;
	virtual void Notify() = 0;
	string SubjectState(string subjectState) {
		this->subjectState = subjectState;
		return subjectState;
	}

protected:
	string subjectState;
};

//具体通知者类
class Subject1 : public AbstractSubject {
public:
	//针对抽象编程,减少了与具体类之间的耦合
	void Attach(AbstractObserver* observer) {
		observers.push_back(observer);
	}

	void Detach(AbstractObserver* observer) {
		observers.remove(observer);
	}

	void Notify() {
		for (list<AbstractObserver*>::iterator it = observers.begin(); it != observers.end(); it++) {
			(*it)->Update(subjectState);
		}
	}

	string SubjectState(string subjectState) {
		this->subjectState = subjectState;
		return subjectState;
	}

private:
	list<AbstractObserver*> observers;
};

//具体观察者类
class Observer1 : public AbstractObserver {
public:
	Observer1(string name, AbstractSubject* _subject){
		Name = name;
		subject = _subject;
	}

	void Update(string subjectState) {
		this->observerState = subject->SubjectState(subjectState);
		cout << "观察者:" << this->Name << " 状态:" << this->observerState << " 停止打游戏" << endl;
	}

protected:
	string Name;
	string observerState;
	AbstractSubject* subject;
};

class Observer2 : public AbstractObserver {
public:
	Observer2(string name, AbstractSubject* _subject) {
		Name = name;
		subject = _subject;
	}

	void Update(string subjectState) {
		this->observerState = subject->SubjectState(subjectState);
		cout << "观察者:" << this->Name << " 状态:" << this->observerState << " 停止刷视频" << endl;
	}

protected:
	string Name;
	string observerState;
	AbstractSubject* subject;
};

//客户端
int main() {
	AbstractSubject* secretory1 = new Subject1();

	secretory1->Attach(new Observer1("小张", secretory1));
	secretory1->Attach(new Observer2("小王", secretory1));

	secretory1->SubjectState("老板回来了!");
	secretory1->Notify();

	system("pause");
	return 0;
}

观察者模式的不足:

尽管已经用了依赖倒转原则,但是“抽象通知者”还是依赖“抽象观察者”,也就是说,万一没有了抽象观察者这样的接口,通知的功能就完不成。另外就是每个具体观察者,它不一定是“更新”的方法要调用。

所以如果通知者和观察者之间相互不知道,可以由客户端来决定通知谁。

后续:可用委托机制来进行改进。

标签:string,observer,void,观察者,模式,observers,subjectState
来源: https://www.cnblogs.com/kyzh-lhl/p/16691129.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有