当前位置: 首页 > news >正文

设计模式(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++)
#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:

#include "Observer.h"void ConcreteObserver::Update(Subject* pSubject) {m_state = pSubject->GetState();cout << "Observer:" << m_name << ",got state from subject:" << m_state << endl;
}
#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代码示意:

#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:

#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;
#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;
}

 运行结果:

http://www.lryc.cn/news/270984.html

相关文章:

  • MySQL所有常见问题
  • 锐捷交换机配置 SNMP
  • Windows 10 安装和开启VNCServer 服务
  • js遍历后端返回的集合将条件相同的放入同一个数组内
  • GcExcel:DsExcel 7.0 for Java Crack
  • 基于SpringBoot的职业生涯规划系统
  • 基于Java+SpringBoot+vue+elementui的校园文具商城系统详细设计和实现
  • PyTorch中常用的工具(5)使用GPU加速:CUDA
  • Qt+opencv 视频分解为图片
  • 一篇文章认识微服务的优缺点和微服务技术栈
  • [spark] dataframe的数据导入Mysql5.6
  • 2023年度业务风险报告:四个新风险趋势
  • python编程从入门到实践(1)
  • ElasticSearch 文档操作
  • NXOpenC++布尔求和命令
  • ubuntu python播放MP3,wav音频和录音
  • Rust学习笔记000 安装
  • python AI五子棋对战
  • 图文证明 费马,罗尔,拉格朗日,柯西
  • CEC2017(Python):粒子群优化算法PSO求解CEC2017(提供Python代码)
  • AUTOSAR从入门到精通- 虚拟功能总线(RTE)(一)
  • B/S架构云端SaaS服务的医院云HIS系统源码,自主研发,支持电子病历4级
  • 看懂基本的电路原理图(入门)
  • 赫夫曼树基本数据结构
  • 10TB海量JSON数据从OSS迁移至MaxCompute
  • LLM之RAG实战(九)| 高级RAG 03:多文档RAG体系结构
  • Windows电脑引导损坏?按照这个教程能修复
  • 记Android字符串资源支持的参数类型
  • Java实现树结构(为前端实现级联菜单或者是下拉菜单接口)
  • MySQL中常用的数据类型