【10】观察者模式

设计场景:

发布-订阅
对于感兴趣的公众号,客户选择了订阅,当公众号发布新文章(伴随着更新发布状态)时,它会通知已订阅的客户们,客户们自身随发布而更新自身状态;


问题描述:

(1)观察者模式定义:一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当这个主题对象自身状态发生变化时,会通知所有观察者对象,是他们能够自动更新自己;
(2)观察者模式很好的体现了开放-封闭原则、依赖倒转原则的思想;解除耦合,让耦合的双方依赖于抽象,而不是依赖于具体;从而使各自的变化不会互相影响;
(3)开放-封闭:对自身扩展开放,对自身修改封闭;
(4)依赖倒转:程序依赖抽象,而不是程序与程序依赖;
(5)使用时机:当一个对象的改变需要同时改变其他对象(不知数量)时;

代码实现:

(1)代码采用观察者模式实现了设计场景中的需求,同时实现过程中尽可能的扣紧观察者模式的定义;
(2)注意:发布与订阅是一对多的关系,这也是在观察者类没有针对抽象主题类编程,而是针对具体主题类编程的原因;若是多对多的关系,可考虑采用针对抽象类编程,可以有效的解除观察者类和主题类之间的耦合;注意当前代码仅仅实现的是降低而不是解除;

#pragma once

#include<vector>
#include<string>
using namespace std;
#include"observe.h"

// 主题类-----抽象类
class Subject
{
public:
	// 添加观察者
	virtual void attach(Observe* observe) = 0;

	// 删除观察者 
	virtual void detach() = 0; // 简化操作:默认只删除最后一个添加的观察者

	// 发布通知
	virtual void notify(string content,string flag) = 0;
};
#pragma once
#include"subject.h"

// 具体主题对象-----继承Subject抽象类
class ConcreteSubject : public Subject
{
public:
	ConcreteSubject() {
		m_state = "未发送";
	}
	void attach(Observe* observe) override // 针对抽象类编程,降低类之间的耦合
	{
		m_observes.push_back(observe);
	}
	void detach() override
	{
		m_observes.pop_back();
	}
	void notify(string content,string flag) override
	{
		for (int i = 0; i < m_observes.size(); i++)
		{
			m_observes.at(i)->update(content,flag);
		}
	}
	// get
	string get_SubjectState() { return m_state; }
	// set
	void set_SubjectState(string state) { m_state = state; }
private:
	vector<Observe*> m_observes; // 观察者集合 (一个主题:多个观察者)
	string m_state; // 状态
}; 
#pragma once
#include<string>
using namespace std;

// 观察者类-----抽象类
class Observe
{
public:
	virtual void update(string content,string flag) = 0; // 更新观察者自身
};
#pragma once
#include"observe.h"
#include"concrete_subject.h"
#include<iostream>

// 具体观察者类-----继承Observe抽象类
class ConcreteObserve : public Observe
{
public:
	ConcreteObserve(ConcreteSubject* subject,string name) // 这里不用抽象类的原因是 (一对多的关系,若是多对多,可以优化成针对抽象编程)
	{
		m_subject = subject;
		m_name = name;
	}

	void update(string content,string flag) override
	{
		if (flag == "已发送")
		{
			m_state = "已收到";
		}
		else
		{
			m_state = "未收到";
		}
		cout << "观察者:" << m_name << "对于主题:" << content << " 展示的新状态是:" << m_state << endl;
	}
private:
	string m_name; // 名称
	string m_state; // 状态
	ConcreteSubject* m_subject; // 订阅的主题
};
#include"concrete_observe.h"
#include"concrete_subject.h"
#include"observe.h"
#include"subject.h"

int main()
{
	// 创建具体主题对象
	ConcreteSubject* s = new ConcreteSubject();
	// 为主题对象添加具体观察者对象   同时将观察者于订阅的主题绑定 (一对多关系)
	s->attach(new ConcreteObserve(s, "阿强"));
	s->attach(new ConcreteObserve(s, "阿珍"));
	// 订阅号主题发布内容,同时将状态置 已发送
	s->notify("元宇宙将重塑人类数字地图","已发送");
}

观察者:阿强对于主题:元宇宙将重塑人类数字地图 展示的新状态是:已收到
观察者:阿珍对于主题:元宇宙将重塑人类数字地图 展示的新状态是:已收到
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值