设计模式(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;
}

运行结果:

相关推荐
丶白泽13 分钟前
重修设计模式-结构型-桥接模式
java·设计模式·桥接模式
南郁2 小时前
把设计模式用起来!(3)用不好模式?之时机不对
设计模式
Lill_bin3 小时前
Lua编程语言简介与应用
开发语言·数据库·缓存·设计模式·性能优化·lua
瞅瞅水5 小时前
设计模式中工厂模式的C语言实现
设计模式
SchneeDuan7 小时前
iOS六大设计原则&&设计模式
ios·设计模式·cocoa·设计原则
Book_熬夜!9 小时前
Python基础(十)——闭包、装饰器、设计模式与多线程编程
开发语言·python·设计模式
java_heartLake18 小时前
设计模式之工厂方法模式
java·设计模式·工厂方法模式
我码玄黄1 天前
JS 的行为设计模式:策略、观察者与命令模式
javascript·设计模式·命令模式
会敲代码的小张1 天前
设计模式-观察者模式
java·开发语言·后端·观察者模式·设计模式·代理模式
宗浩多捞1 天前
C++设计模式(更新中)
开发语言·c++·设计模式