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

观察者模式 行为型设计模式之七

1.定义

        在GOF的《设计模式:可复用面向对象软件的基础》一书中对观察者模式是这样定义的:定义对象的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。当一个对象发生了变化,关注它的对象就会得到通知;这种交互也成为发布-订阅(publish-subscribe)。

2.组成结构

  1. Subject(目标):目标知道它的观察者,可以有任意多个观察者观察用一个目标,提供注册和删除观察者对象的接口。
  2. Observer(观察者):为所有观察目标的观察者对象提供一个公共的更新接口。
  3. ConcreteSubject(具体目标):将有关状态的情况广播给各ConcreteObserver对象。
  4. ConcreteObserver(具体观察者):维护一个指向ConcreteSubject对象的指针,用于当具体观察者初始化时直接存入ConcreteSubject对象(初始化就订阅ConcreteSubject主题);存储有有关状态,这些状态应与目标的状态保持一致;实现Observer公共更新接口以便使自身状态和目标状态保持一致。

3.示例代码

#include <iostream>
#include <list>
using std::cout;
using std::endl;
using std::cin;class Observer
{
public:virtual ~Observer() {};virtual void Update(int) = 0;
};class Subject
{
public:virtual ~Subject() {};virtual void Attach(Observer*) = 0;virtual void Detach(Observer*) = 0;virtual void Notify() = 0;
};class ConcreteObserver : public Observer
{
private:Subject* _pSubject;public:ConcreteObserver(Subject* pSubject) :_pSubject(pSubject){//在目标中注册当前观察者(此处的观察者是广义上的观察者,目标并不知道具体谁要观察它,目标只进行广播即可)this->_pSubject->Attach(this);cout << "I'm the observer \" 1 \".\n";}void Update(int value) override{cout << "ConcreteObserver get the update.New State:" << value << endl;}
};class ConcreteObserver2 : public Observer
{
private:Subject* _pSubject;public:ConcreteObserver2(Subject* pSubject) :_pSubject(pSubject){//在目标中注册当前观察者(此处的观察者是广义上的观察者,目标并不知道具体谁要观察它,目标只进行广播即可)this->_pSubject->Attach(this);cout << "I'm the observer \" 2 \".\n";}void Update(int value) override{cout << "ConcreteObserver2 get the update.New State:" << value << endl;}
};class ConcreteSubject :public Subject
{
private:std::list<Observer*> _pObserverList;int _iState;
public:void SetState(int state){_iState = state;}void Attach(Observer* pObserver) override{_pObserverList.push_back(pObserver);}void Detach(Observer* pObserver) override{_pObserverList.remove(pObserver);}void Notify() override{auto begin = _pObserverList.begin();auto end = _pObserverList.end();while (begin != end){(*begin)->Update(_iState);begin++;}}
};int main()
{//创建目标ConcreteSubject* pSubject = new ConcreteSubject();//创建观察者Observer* pObserver = new ConcreteObserver(pSubject);Observer* pObserver2 = new ConcreteObserver2(pSubject);//改变当前状态pSubject->SetState(2);//广播给所有广义上的观察者pSubject->Notify();//去除某个观察者pSubject->Detach(pObserver);//改变当前状态pSubject->SetState(3);//重新广播pSubject->Notify();//结束,释放对象delete pObserver;delete pObserver2;delete pSubject;return 0;
}

4.使用说明

意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。

主要解决:一个对象状态改变并给其它对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

如何解决:使用面向对象技术,可以将这种依赖关系弱化。

关键代码:在抽象类里有一个arrayList存放观察者们。

应用实例:1、拍卖的时候,拍卖师观察最高价格,然后通知给其它竞价者竞价。2、西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水找来一个老乌龟,这个老乌龟就是观察者(菩萨是被观察者),他观察菩萨这个动作。

优点:1、观察者和被观察者是抽象耦合的。2、建立一套触发机制。

缺点:1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

使用场景:

  1. 一个抽象模型有两个方面,其中一个方面发依赖于另外一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  2. 一个对象的改变将导致其它一个或多个对象发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  3. 一个对象必须通知其他对象,而并不知道这些对象是谁。
  4. 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

注意事项:1、应避免循环引用。2、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式(多线程)。
 

引用

C++观察者模式_c++ observer-CSDN博客

 

相关文章:

观察者模式 行为型设计模式之七

1.定义 在GOF的《设计模式&#xff1a;可复用面向对象软件的基础》一书中对观察者模式是这样定义的&#xff1a;定义对象的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。当一个对象发生了变化&#xff0…...

数据结构与算法之堆: Leetcode 451. 根据字符出现频率排序 (Typescript版)

根据字符出现频率排序 https://leetcode.cn/problems/sort-characters-by-frequency/ 描述 给定一个字符串 s &#xff0c;根据字符出现的 频率 对其进行 降序排序 。一个字符出现的 频率 是它出现在字符串中的次数。返回 已排序的字符串 。如果有多个答案&#xff0c;返回其…...

吃透底层:从路由到前缀树

前言 今天学到关于路由相关文章&#xff0c;发现动态路由中有一个很常见的实现方式是前缀树&#xff0c;很感兴趣这个算法&#xff0c;故进行记录。 前缀树 Trie&#xff08;又被叫做字典树&#xff09;可以看作是一个确定有限状态自动机&#xff0c;尽管边上的符号一般是隐含…...

SparkSQL外部数据源

1.简介 1.1 多数据源支持 Spark 支持以下六个核心数据源,同时 Spark 社区还提供了多达上百种数据源的读取方式,能够满足绝大部分使用场景。 - CSV - JSON - Parquet - ORC - JDBC/ODBC connections - Plain-text files 1.2 读数据格式 所有读取 API 遵循以下调用格式: // …...

林沛满-TCP 是如何避免被发送方分片的?

TCP 可以避免被发送方分片&#xff0c;是因为它主动把数据分成小段再交给网络层。最大的分段大小称为 MSS&#xff08;Maximum Segment Size&#xff09;&#xff0c;它相当于把 MTU 刨去 IP头和 TCP 头之后的大小&#xff0c;所以一个 MSS 恰好能装进一个 MTU 中。 图4 图 4 …...

Java中的枚举是什么?

Java枚举详解 枚举&#xff08;Enum&#xff09;是Java编程语言中的一种特殊数据类型&#xff0c;它用于表示一组具名的常量。枚举提供了一种更加类型安全和易于理解的方式来表示常量值&#xff0c;使代码更加清晰和可维护。 为什么需要枚举&#xff1f; 在介绍Java枚举的具…...

java学习--day24(单例模式序列化Lambda表达式)

文章目录 回顾今天的内容1.单例模式2.序列化3.Lambda表达式3.1入门案例3.2lambda表达式语法格式3.2.1无参无返回值的形式3.2.2有参无返返回值的方法3.2.3无参有返回值3.2.4有参有返回值的 回顾 1.三种创建Class对象的形式Class.forName("")类.class对象.getCalss()字…...

从0开始学go第六天

方法一&#xff1a;gin获取querystring参数 package main//querystring import ("net/http""github.com/gin-gonic/gin" )func main() {r : gin.Default()r.GET("/web", func(c *gin.Context) {//获取浏览器那边发请求携带的query String参数//…...

unity设计模式——代理模式

Subject类&#xff0c;定义了Real Subject和Proxy的共用接口&#xff0c;这样就在任何使用Real Subject的地方都可以使用Proxy。 abstract class Subject : MonoBehaviour {public abstract void Request(); } RealSubject类&#xff0c;定义Proxy所代表的真实实体。 class R…...

SpringBoot 如何使用 Grafana 进行可视化监控

使用Spring Boot Sleuth进行分布式跟踪 在现代分布式应用程序中&#xff0c;跟踪请求和了解应用程序的性能是至关重要的。Spring Boot Sleuth是一个分布式跟踪解决方案&#xff0c;它可以帮助您在分布式系统中跟踪请求并分析性能问题。本文将介绍如何在Spring Boot应用程序中使…...

【Codeforces】 CF1762E Tree Sum

题目链接 CF方向 Luogu方向 题目解法 首先考虑 n n n 为奇数的情况无解&#xff0c;这个可以通过乘积矛盾简单证明 接下来考虑一个结论是&#xff1a;偶数个点的树的形态确定之后&#xff0c;只有恰好 1 1 1 种染色方案&#xff0c;即从叶子一层一层往上面染&#xff0c;…...

用《斗破苍穹》的视角打开C#委托2 委托链 / 泛型委托 / GetInvocationList

委托链 经过不懈地努力&#xff0c;我终于成为了斗师&#xff0c;并成功掌握了两种斗技——八极崩和焰分噬浪尺。于是&#xff0c;我琢磨着&#xff0c;能不能搞一套连招&#xff0c;直接把对方带走。 using System; using System.Collections.Generic; using System.Linq; u…...

唐老师讲电赛

dc-dc电源布局要点...

[ICCV-23] DeformToon3D: Deformable Neural Radiance Fields for 3D Toonification

pdf | code 将3D人脸风格化问题拆分为几何风格化与纹理风格化。提出StyleField&#xff0c;学习以风格/ID为控制信号的几何形变残差&#xff0c;实现几何风格化。通过对超分网络引入AdaIN&#xff0c;实现纹理风格化。由于没有修改3D GAN空间&#xff0c;因此可以便捷实现Edit…...

配置Hive使用Spark执行引擎

配置Hive使用Spark执行引擎 Hive引擎概述兼容问题安装SparkSpark配置Hive配置HDFS上传Spark的jar包执行测试速度对比 Hive引擎 概述 在Hive中&#xff0c;可以通过配置来指定使用不同的执行引擎。Hive执行引擎包括&#xff1a;默认MR、tez、spark MapReduce引擎&#xff1a; 早…...

基于FPGA的视频接口之千兆网口(五应用)

简介 相信网络上对于FPGA驱动网口的开发板、博客、论坛数不胜数,为何博主需要重新手敲一遍呢,而不是做一个文抄君呢!因为目前博主感觉网络上描述的多为应用层上的开发,非从底层开始说明,本博主的思虑还是按照老规矩,按照硬件、底层、应用等关系,使用三~四篇文章,来详细…...

车载开发所学内容,有哪些?程序员的转岗位需求

一、高速发展的行业前景 随着全球智能汽车市场的飞速发展&#xff0c;车载开发行业的前景可谓一片光明。各国政府对于自动驾驶和智能交通系统的政策支持&#xff0c;为行业带来了前所未有的机遇。此外&#xff0c;人工智能、大数据、云计算等前沿技术的不断突破&#xff0c;为…...

VSCode Intellij IDEA CE 数据库连接

VSCode & Intellij IDEA CE 数据库连接 大概记一下现在正在用的几个工具/插件 VSCode VSCode 里面的工具我下载了很多&#xff0c;如果只是链接 MySQL 的话&#xff0c;可能用 Jun Han 这位大佬的 MySQL 就好了&#xff1a; 使用这个插件直接打开 .sql 文件单击运行就能…...

直流无刷电机开发应用

下面的链接是笔者在研究无刷电机的过程中&#xff0c;找到的业内无刷电机驱动龙头企业&#xff0c;峰岹科技的各类无刷电机应用设计参考&#xff0c;比较有学习和借鉴意义。 应用手册 - 峰岹科技...

c 语言基础题目:PTA L1-030 一帮一

“一帮一学习小组”是中小学中常见的学习组织方式&#xff0c;老师把学习成绩靠前的学生跟学习成绩靠后的学生排在一组。本题就请你编写程序帮助老师自动完成这个分配工作&#xff0c;即在得到全班学生的排名后&#xff0c;在当前尚未分组的学生中&#xff0c;将名次最靠前的学…...

年度名场面!黄仁勋逛胡同被投喂豆汁,眉头紧锁。网友:弥补了没有喝过 XX 的遗憾

5 月 15 日&#xff0c;「黄仁勋 南锣鼓巷」话题突然在多平台引爆热议。谁能想到&#xff0c;手握 5 万亿美刀市值的科技大佬&#xff0c;私下里竟是胡同干饭人。昨天在大会堂还是西装革履&#xff0c;今天老黄换上他的经典皮肤套装&#xff0c;带几名随行人员低调逛南锣鼓巷和…...

探索GitHub导航菜单:平台功能、解决方案、资源及GlycemicGPT项目全揭秘

导航菜单包含登录、外观设置等选项&#xff0c;还有平台、解决方案、资源、开源、企业版等板块。平台有AI代码创作&#xff08;如GitHub Copilot、GitHub Spark等&#xff09;、开发者工作流&#xff08;如Actions、Codespaces等&#xff09;、应用程序安全&#xff08;如GitHu…...

基于Terraform与Azure的Dify AI平台云原生自动化部署实践

1. 项目概述&#xff1a;一键部署AI应用平台的云原生方案最近在折腾AI应用开发平台&#xff0c;发现很多团队在从本地原型验证转向云端生产环境时&#xff0c;总会遇到一堆“部署地狱”的问题。环境配置不一致、资源管理混乱、成本不可控&#xff0c;这些问题在需要整合多个AI模…...

Arduino智能小车避障与拟人化设计:从传感器到行为逻辑

1. 项目概述与核心思路最近在整理工作室的物料&#xff0c;翻出了几个闲置的360度舵机和超声波模块&#xff0c;手痒之下决定做个智能小车玩玩。这个项目本身不新鲜&#xff0c;网上教程一抓一大把&#xff0c;但我想做点不一样的&#xff1a;不仅要能实现基础的自动避障&#…...

会议录播堆积如山?用这款AI工具3分钟自动生成会议纪要

一个很普遍的职场痛点&#xff1a;每周开3-4个会&#xff0c;录播存了一堆&#xff0c;但从来没有整理过。 不是不想整理&#xff0c;是整理一小时的会议录像至少要40分钟——要从头拉一遍、要标重点、要区分谁说了什么、要提炼行动项。忙的时候根本没时间干这个。 结果就是&…...

Zeek日志AI分析平台:从网络监控到智能威胁检测的架构与实践

1. 项目概述&#xff1a;从开源网络监控到智能分析的进化如果你在网络安全、运维或者数据分析领域摸爬滚打过几年&#xff0c;大概率听说过 Zeek&#xff08;以前叫 Bro&#xff09;。它不是一个简单的入侵检测系统&#xff0c;而是一个功能强大的网络分析框架&#xff0c;能够…...

容器化应用分发平台seait:简化部署流程,实现一键运行

1. 项目概述&#xff1a;一个面向开发者的容器化应用分发平台最近在折腾个人项目部署和团队协作时&#xff0c;我一直在思考一个问题&#xff1a;如何能像分发一个可执行文件一样&#xff0c;轻松地分享和运行一个完整的、包含所有依赖的应用程序&#xff1f;尤其是在跨平台、跨…...

c++ 动态链接器audit c++如何使用ld_audit监控so加载过程

Oracle监听端口被占用导致TNS-12541错误&#xff0c;需检查并更换端口&#xff08;如1522&#xff09;&#xff0c;同步更新listener.ora、tnsnames.ora及JDBC连接串&#xff0c;重启监听&#xff1b;EM Express需单独配置HTTP端口&#xff1b;Windows下还需手动开放防火墙新端…...

UPS 蓄电池在线监控系统是什么?工业 UPS 电源有必要安装吗?

在机房、工业生产、医疗设备等依赖 UPS 不间断电源的场景中&#xff0c;蓄电池往往被视为设备的 “心脏”。很多用户配置了优质 UPS 电源&#xff0c;却忽略了对蓄电池的实时管理&#xff0c;等到突发停电才发现电池亏电、失效&#xff0c;导致 UPS 无法正常供电&#xff0c;引…...

全栈代码资源聚合库:开发者如何高效利用开源代码示例提升工程能力

1. 项目概述&#xff1a;一个面向开发者的全栈代码资源聚合库最近在GitHub上看到一个挺有意思的项目&#xff0c;叫wuwangzhang1216/claude-code-source-all-in-one。光看这个名字&#xff0c;你大概能猜到这是个什么——没错&#xff0c;这是一个围绕“代码”和“源代码”做文…...