设计模式(C++)-行为型模式-观察者模式

设计模式(C++)-行为型模式-观察者模式

一、观察者模式概述

观察者模式(Oberserve Pattern)是一种行为型设计模式,用于对象间建立一种一对多的依赖关系,当一个对象(被观察者)状态改变时,所有依赖它的对象(观察者)都会自动得到通知并更新。

二、观察者模式UML类图

场景:游戏中英雄打boss

模拟游戏世界中,英雄组团打boss的场景,可以通过观察者模式实现,具体UML类图如下:

三、代码实现

cpp 复制代码
//observe.h
#pragma once
/*Observer 模式(观察者模式)
Observer 模式要解决的问题为:建立一个一(Subject)对多(Observer)的依赖关系,并且做到当"一"变化的时候,
依赖这个"一"的多也能够同步改变。最常见的一个例子就是:对同一组数据进行统计分析时候,我们希望能够提供多
种形式的表示(例如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。指多个对象间存在一对多的依赖关系,
当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
发布订阅模式是观察者模式演变而来,加入了主题队列
举例:
Subject 提供依赖于它的观察者 Observer 的注册(registerObserver)和注销(remove)操作,
并且提供了使得依赖于它的所有观察者同步的操作(notifyObserver),观察者 Observer 则提供一个 Update 操作,
注意这里的 Observer 的 Update 操作并不在 Observer 改变了 Subject 目标状态的时候就对自己进行更新,
这个更新操作要延迟到 Subject 对象发出 Notify 通知所有Observer 进行修改(调用 Update)。
*/
#include <iostream>
#include <list>
using namespace std;

//抽象的英雄 抽象的观察者  Observer
class AbstractHero{
public:
	virtual void Update() = 0;
};

//具体的英雄 具体的观察者
class HeroA :public AbstractHero {
public:
	HeroA() {
		cout << "英雄A正在鲁BOSS" << endl;
	}
	virtual void Update() {
		cout << "英雄A停止鲁,待机状态" << endl;
	}
};
class HeroB :public AbstractHero {
public:
	HeroB() {
		cout << "英雄B正在鲁BOSS" << endl;
	}
	virtual void Update() {
		cout << "英雄B停止鲁,待机状态" << endl;
	}
};
class HeroC :public AbstractHero {
public:
	HeroC() {
		cout << "英雄C正在鲁BOSS" << endl;
	}
	virtual void Update() {
		cout << "英雄C停止鲁,待机状态" << endl;
	}
};
class HeroD :public AbstractHero {
public:
	HeroD() {
		cout << "英雄D正在鲁BOSS" << endl;
	}
	virtual void Update() {
		cout << "英雄D停止鲁,待机状态" << endl;
	}
};
class HeroE :public AbstractHero {
public:
	HeroE() {
		cout << "英雄E正在鲁BOSS" << endl;
	}
	virtual void Update() {
		cout << "英雄E停止鲁,待机状态" << endl;
	}
};

//定义抽象的观察目标  Subject
class AbstractBoss
{
public:
	//添加观察者 对象
	virtual void addHero(AbstractHero*hero) = 0;
	//移除观察者 对象
	virtual void removeHero(AbstractHero*hero) = 0;
	//通知所有观察者对象
	virtual void notify() = 0;
};

//相当于 concreteSubject
class BOSSA:public AbstractBoss
{
public:
	//添加观察者 对象
	virtual void addHero(AbstractHero*hero) {
		pHeroList.emplace_back(hero);
	}
	//移除观察者 对象
	virtual void removeHero(AbstractHero*hero) {
		pHeroList.remove(hero);
	}
	//通知所有观察者对象
	virtual void notify() {
		for (auto iter = pHeroList.begin(); iter != pHeroList.end(); ++iter) {
			(*iter)->Update();
		}
	}

private:
	list<AbstractHero*> pHeroList;
};

void testObserver();

//obeserve.cpp
#include "observer.h"
void testObserver() {
	cout << "=================observer start===============" << endl;
	//创建观察者
	AbstractHero* heroA = new HeroA();
	AbstractHero* heroB = new HeroB();
	AbstractHero* heroC = new HeroC();
	AbstractHero* heroD = new HeroD();
	AbstractHero* heroE = new HeroE();

	//创建观察目标
	AbstractBoss* bossA = new BOSSA();
	bossA->addHero(heroA);
	bossA->addHero(heroB);
	bossA->addHero(heroC);
	bossA->addHero(heroD);
	bossA->addHero(heroE);

	cout << "heroC阵亡" << endl;
	bossA->removeHero(heroC);

	cout << "Boss死了,通知其他英雄停止攻击..." << endl;
	bossA->notify();

	cout << "=================observer end===============" << endl;
}

四、优缺点总结

优点:

  • 松耦合:观察者与被观察者之间是抽象耦合
  • 扩展性好:新增观察者无需修改主题代码
  • 支持广播通信:一次状态变化可通知多个对象
  • 遵循开闭原则:对扩展开放,对修改关闭

缺点:

  • 内存泄露风险:需要正确处理观察者的生命周期
  • 通知顺序不确定:观察者被调用的顺序不确定
  • 性能开销:观察者数量多时通知开销大
  • 循环引用:可能导致内存无法释放

五、适用场景

  • GUI事件处理:按钮点击、窗口变化
  • 发布-订阅系统:消息队列、事件总线
  • 数据监控:传感器数据变化、系统状态监控
  • 游戏开发:游戏事件、状态变化通知
  • 金融系统:股票价格变化、交易信号
  • 分布式系统:配置更新、服务发现
  • 实时数据处理:流式计算、实时分析
相关推荐
故事和你913 小时前
洛谷-算法2-1-前缀和、差分与离散化1
开发语言·数据结构·c++·算法·深度优先·动态规划·图论
handler0111 小时前
从零实现自动化构建:Linux Makefile 完全指南
linux·c++·笔记·学习·自动化
我头发多我先学12 小时前
C++ 模板全解:从泛型编程初阶到特化、分离编译进阶
java·开发语言·c++
星星码️13 小时前
C++选择题练习(一)
开发语言·c++
小苗卷不动15 小时前
OJ练习之疯狂的自我检索者(简单)
c++
LUVK_15 小时前
第七章查找
数据结构·c++·考研·算法·408
迷途之人不知返15 小时前
vector
c++
khalil102015 小时前
代码随想录算法训练营Day-31贪心算法 | 56. 合并区间、738. 单调递增的数字、968. 监控二叉树
数据结构·c++·算法·leetcode·贪心算法·二叉树·递归
小苗卷不动16 小时前
进程与线程的核心区别
c++