设计模式(4)--对象行为(7)--观察者

1. 意图

定义对象间的一种一对多的依赖关系,

当一个对象的状态改变时,所有依赖于它的对象都得到通知并被自动更新。

2. 四种角色

抽象目标(Subject)、具体目标(Concrete Subject)、抽象观察者(Observer)、

具体观察者(Concrete Observer)

3. 优点

3.1 目标和观察者之间的耦合是抽象的。

3.2 支持广播通信。

4. 缺点

4.1 可能导致意外的更新。

5. 相关模式

当目标和观察者间的依赖关系特别复杂时,需要一个维护这些关系的对象,

这样的对象称为ChangeMananger。

5.1 ChangeManager可使用单例模式来保证它是唯一的并且是可全局访问的。

5.2 ChangeManager充当目标和观察者之间的Mediator

6. 代码示意(C++)
cpp 复制代码
#pragma once
#include <string>
#include <iostream>
#include <vector>
using namespace std;

class Subject;

class Observer
{
public:
	virtual void Update(Subject* pSubject) = 0;
protected:
	Observer() {}
};
class ConcreteObserver :public Observer
{
	string m_state;
	string m_name;
public:
	ConcreteObserver(const string& name) :m_name(name) {
	}
	virtual void Update(Subject* pSubject);
};

class Subject
{
	vector<Observer*> m_observers;
public:
	virtual string GetState() = 0;
	virtual void SetState(const string& state) = 0;
public:
	void Attach(Observer* pObserver) {
		m_observers.emplace_back(pObserver);
		cout << "After attached, observers size is:" << m_observers.size() << endl;
	}
	void Detach(Observer* pObserver) {
		m_observers.erase(std::remove_if(m_observers.begin(), m_observers.end(), [&](Observer* p) { return p == pObserver; }), m_observers.end());
		cout << "After detached, observers size is:" << m_observers.size() << endl;
	}
	void Notify()
	{
		auto it = m_observers.begin();
		while (it != m_observers.end()) {
			(*it)->Update(this);
			++it;
		}
	}
protected:
	Subject(){}
};
class ConcreteSubject :public Subject
{
	string m_state;
public:
	virtual string GetState() {
		return m_state;
	}
	virtual void SetState(const string& state) {
		m_state = state;
	}
};

Observer.cpp:

cpp 复制代码
#include "Observer.h"

void ConcreteObserver::Update(Subject* pSubject) {
	m_state = pSubject->GetState();
	cout << "Observer:" << m_name << ",got state from subject:" << m_state << endl;
}
cpp 复制代码
#include "Observer.h"
int main() {
	Subject* pSubject = new ConcreteSubject();

	Observer* pObserver1 = new ConcreteObserver("obs1");
	Observer* pObserver2 = new ConcreteObserver("obs2");

	pSubject->Attach(pObserver1);
	pSubject->Attach(pObserver2);

	pSubject->SetState("hello1");
	pSubject->Notify();

	pSubject->Detach(pObserver1);
	pSubject->SetState("hello2");
	pSubject->Notify();

	delete pObserver2;
	delete pObserver1;
	delete pSubject;
	return 0;
}

运行结果:

6.1 目标和观察者之间只知道彼此的抽象类(3.1)。

6.2 Subject::Notify里的循环就是广播,观察者自己决定是否处理某一通知(3.2)。

6.3 使用ChangeMananger会使代码复杂些,但简化了Subject,且使更新策略更加灵活。

使用ChangeMananger代码示意:

cpp 复制代码
#pragma once
#include <string>
#include <iostream>
#include <vector>
#include <map>
using namespace std;

class Subject;

class Observer
{
public:
	virtual void Update(Subject* pSubject) = 0;
	virtual string GetName() = 0;
protected:
	Observer() {}
};
class ConcreteObserver :public Observer
{
	string m_state;
	string m_name;
public:
	ConcreteObserver(const string& name) :m_name(name) {
	}
	virtual string GetName() { return m_name; }
	virtual void Update(Subject* pSubject);
};

class ChangeManager;
class SimpleChangeManager;

class Subject
{
	ChangeManager* m_pChangeManager;
public:
	virtual string GetState() = 0;
	virtual void SetState(const string& state) = 0;
	virtual ~Subject();
public:
	void Attach(Observer* pObserver);
	void Detach(Observer* pObserver);
	void Notify();
protected:
	Subject();
};
class ConcreteSubject :public Subject
{
	string m_state;
public:
	ConcreteSubject() {
	}
	virtual string GetState() {
		return m_state;
	}
	virtual void SetState(const string& state) {
		m_state = state;
	}
};

class ChangeManager
{
public:
	virtual void Register(Subject* pSubject, Observer* pObserver) = 0;
	virtual void Unregister(Subject* pSubject, Observer* pObserver) = 0;
	virtual void Notify() = 0;
protected:
	ChangeManager() {}
};

class SimpleChangeManager :public ChangeManager
{
	map<Subject*, vector<Observer*> > m_mapSubjects;
private:
	static SimpleChangeManager* s_instance;
public:
	static ChangeManager* Instance() {
		if (0 == s_instance) {
			s_instance = new SimpleChangeManager();
		}
		return s_instance;
	}
    static void DelInstance() {
		delete s_instance;
		s_instance = 0;
	}
public:
	virtual void Register(Subject* pSubject, Observer* pObserver) {
		vector<Observer*>& observers = m_mapSubjects[pSubject];
		auto it = find(observers.begin(), observers.end(), pObserver);
		if (it == observers.end()) {
			observers.emplace_back(pObserver);
			cout << pObserver->GetName() << " is registered successful" << endl;
		}
		else {
			cout << pObserver->GetName() << " is already registered" << endl;
		}
	}
	virtual void Unregister(Subject* pSubject, Observer* pObserver) {
		auto it = m_mapSubjects.find(pSubject);
		if (it == m_mapSubjects.end()) {
			cout << "No need unregister in map for:" << pObserver->GetName() << endl;
		}
		else {
			vector<Observer*>& observers = m_mapSubjects[pSubject];
			auto itRemove = remove_if(observers.begin(), observers.end(), [&](Observer* p) { return p == pObserver; });
			if (itRemove == observers.end()) {
				cout << "No need unregister in vector for:" << pObserver->GetName() << endl;
			}
			else {
				observers.erase(itRemove, observers.end());
				cout << pObserver->GetName() << " is unregistered successful" << endl;
				if (observers.size() == 0) {
					m_mapSubjects.erase(pSubject);
				}
			}
		}
	}
	virtual void Notify() {
		for (auto& pair : m_mapSubjects) {
			vector<Observer*>& observers = pair.second;
			auto it = observers.begin();
			while (it != observers.end()) {
				(*it)->Update(pair.first);
				++it;
			}
		}
	}
protected:
	SimpleChangeManager() {}
};

Observer.cpp:

cpp 复制代码
#include "Observer.h"

void ConcreteObserver::Update(Subject* pSubject) {
	m_state = pSubject->GetState();
	cout << "Observer:" << m_name << ",got state from subject:" << m_state << endl;
}

Subject::Subject() {
	m_pChangeManager = SimpleChangeManager::Instance();
}
Subject::~Subject() {
	m_pChangeManager = 0;
	SimpleChangeManager::DelInstance();
}
void Subject::Attach(Observer* pObserver) {
	m_pChangeManager->Register(this, pObserver);
}
void Subject::Detach(Observer* pObserver) {
	m_pChangeManager->Unregister(this, pObserver);
}
void Subject::Notify()
{
	m_pChangeManager->Notify();
}

SimpleChangeManager* SimpleChangeManager::s_instance = 0;
cpp 复制代码
#include "Observer.h"
int main() {

	Subject* pSubject = new ConcreteSubject();

	Observer* pObserver1 = new ConcreteObserver("obs1");
	Observer* pObserver2 = new ConcreteObserver("obs2");

	pSubject->Attach(pObserver1);
	pSubject->Attach(pObserver2);
	pSubject->Attach(pObserver1);

	pSubject->SetState("hello1");
	pSubject->Notify();

	pSubject->Detach(pObserver1);
	pSubject->Detach(pObserver1);
	pSubject->SetState("hello2");
	pSubject->Notify();

	pSubject->Detach(pObserver2);
	pSubject->Detach(pObserver2);

	delete pObserver2;
	delete pObserver1;
	delete pSubject;
	return 0;
}

运行结果:

相关推荐
George_Ye37 分钟前
同一本书,一人一份:我如何设计 AI 个性化扫书报告
设计模式
莫得感情 o10 小时前
设计模式 22 · 三个冷门模式:中介者、访问者、解释器
java·设计模式
AI人工智能+电脑小能手1 天前
大白话说Java设计模式-08-建造者模式(业务实战篇)
java·设计模式·建造者模式·架构设计·对象构建
AustinXu1 天前
从 Claude Code 到 Claude Tag,Harness Engineering 走到了组织这一层
设计模式·团队管理
剧中有戏1 天前
单例模式从入门到精通:一个数据库连接池的完整剖析
设计模式
胡萝卜术1 天前
编译期与运行期的双重防线:从 TypeScript 类型之争到 LLM 输出的自动化择优
前端·设计模式·面试
货拉拉技术1 天前
重塑 Agent 度量衡:基于 LLM-as-a-Judge 的离线评估体系与实践
算法·设计模式
KhalilRuan1 天前
设计模式小记
设计模式
卡牌RWA研究院1 天前
Relique:一张精品卡牌如何从收藏品变成可交易的链上资产?
设计模式·金融·区块链·创业创新
剧中有戏2 天前
抽象工厂模式从入门到精通:一个多云存储案例的完整剖析(修订版)
设计模式