C++实现观察者模式(包含源码)

文章目录

    • 观察者模式
      • 一、基本概念
      • 二、实现方式
      • 三、角色
      • 四、过程
      • 五、结构图
      • 六、构建思路
      • 七、完整代码

观察者模式

一、基本概念

观察者模式(又被称为模型(Model)-视图(View)模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。

二、实现方式

观察者模式有很多实现方式,从根本上说,该模式必须包含两个角色:观察者和被观察者。

比如在下面的代码表述中,发布作品的DY博主是被观察者,博主的粉丝是观察者 ,当DY博主(被观察者) 发生某种变化时 (状态改变),就会立即通知博主的粉丝 (观察者 )。

三、角色

1、抽象主题(Subject):

它是一个抽象类,也是所有目标对象的父类。它用一个列表记录当前目标对象有哪些观察者对象,并提供增加(Add)、删除观察者对象(Delete)和通知观察者对象的接口。

2、具体主题(ConcreteSubject):

具体目标类,可以有多个不同的具体目标类,它们同时继承Subject类。一个目标对象就是某个具体目标类的对象,一个具体目标类负责定义它自身的事务逻辑,并在状态改变时通知它的所有观察者对象。

3、抽象观察者(Observer):

观察者类,它也是一个抽象类,是所有观察者对象的父类;它为所有的观察者对象都定义了一个名为show的方法(也叫成员函数)。当目标对象的状态改变时,它就是通过调用它的所有观察者对象的show方法来通知它们的。

4、具体观察者(ConcreteObserver):

具体观察者类,可以有多个不同的具体观察者类,它们同时继承Observer类。一个观察者对象就是某个具体观察者类的对象。每个具体观察者类都要重定义Observer类中定义的show方法,在该方法中实现它自己的任务逻辑,当它被通知的时候(目标对象调用它的show方法)就执行自己特有的任务。

四、过程

实现观察者模式有很多形式,比较直观的一种是使用一种“注册—通知—撤销注册”的形式。

观察者

(Observer)将自己注册到被观察对象(Subject)中,被观察对象将观察者存放在一个容器(Container)里。

被观察对象

被观察对象发生了某种变化,从容器中得到所有注册过的观察者,将变化通知观察者。

撤销观察

观察者告诉被观察者要撤销观察,被观察者从容器中将观察者去除。

五、结构图

img

六、构建思路

我们在前期已经了解了observer和subject的代表意义及用法,下面我们开始构思如何写代码

先写出subject和observer类定义用法

class Observer
{
public:virtual void update(){};virtual std::string getName(){return "";}
};class Subject 
{
public:void Add(Observer *obs);void Delete(Observer *obs);void show();~Subject();
private:std::vector<Observer *>observer;
};

Observer中的成员函数都是虚函数,不需要强调其作用,只需要了解虚函数的用法;

Subject类的成员函数及变量:

void Add(Observer *obs)---------------增加观察者

void Delete(Observer *obs)------------删除观察者

void show()-----------------------------------当被观察者状态发生改变时,及时通知观察者

~Subject()-------------------------------------析构函数,创建了许多观察者,最后需要析构删除

std::vector<Observer *>observer-----存放观察者的信息,观察者存放到vector容器中

具体主题(ConcreteSubject)和具体观察者(ConcreteObserver)的类定义

class ConcreteSubject : public Subject
{
public:std::string getSubjectStatus();void   setSubjectStatus(ConcreteSubject * subject, const std::string &str);
private:std::string subjectStatus;
};class ConcreteObserver : public Observer
{
public:ConcreteObserver(ConcreteSubject *subject,std::string name);std::string getName();void update();
private:std::string name;ConcreteSubject *subject;std::string observerStatus;
};

具体主题(ConcreteSubject)类的成员函数及成员变量

std::string getSubjectStatus() -------------------获得被观察者的状态

void setSubjectStatus(ConcreteSubject * subject, const std::string &str) ------------设置被观察者的状态

std::string subjectStatus---------------------------被观察者状态的变量

具体主题(ConcreteObserver)类的成员函数及成员变量

ConcreteObserver(ConcreteSubject *subject,std::string name)---------构造函数,初始化具体观察者

std::string getName()-----------得到观察者的名字

void update() ----------------------当被观察者状态改变时,提醒观察者

std::string observerStatus-----观察者状态

七、完整代码

observer.h

#include<iostream>
#include<vector>class Observer
{
public:virtual void update(){};virtual std::string getName(){return "";}
};
class Subject 
{
public:void Add(Observer *obs);void Delete(Observer *obs);void show();~Subject();
private:std::vector<Observer *>observer;
};
class ConcreteSubject : public Subject
{
public:std::string getSubjectStatus();void   setSubjectStatus(ConcreteSubject * subject, const std::string &str);
private:std::string subjectStatus;
};
class ConcreteObserver : public Observer
{
public:ConcreteObserver(ConcreteSubject *subject,std::string name);std::string getName();void update();
private:std::string name;ConcreteSubject *subject;std::string observerStatus;
};

observer.cpp

#include "observer.h"
#include<iostream>void Subject::Add(Observer *obs)
{observer.push_back(obs);
}
void Subject::Delete(Observer *obs)
{for(auto i = 0;i < observer.size();i++){if(obs == observer[i]){observer.erase(observer.begin() + i);}}
}
void Subject::show()
{auto it = observer.begin();  //vector<Observer*>::iteratorwhile(it != observer.end())  {(*it)->update();        // it是指向observer元素的地址类似于observer.begin()。*it才相当于 observer[i]it++;}
}
Subject::~Subject()
{std::cout<<"执行析构函数------"<<std::endl;auto it = observer.begin();while(it != observer.end()){std::cout<<"已经删除:"<<(*it)->getName()<<std::endl;delete *it;it++;}observer.clear();
}
std::string ConcreteSubject::getSubjectStatus()
{return subjectStatus;
}
void ConcreteSubject::setSubjectStatus(ConcreteSubject * subject,const std::string &str)
{subjectStatus = str;subject->show();
}
ConcreteObserver::ConcreteObserver(ConcreteSubject *subject,std::string name)
{this->subject = subject;this->name = name;
}
std::string ConcreteObserver::getName()
{return name;
}
void ConcreteObserver::update()
{observerStatus = subject->getSubjectStatus();std::cout<<"您关注的DY博主更新动态了    粉丝: "<<name<<"用户状态: "<<observerStatus<<std::endl;
}

main.cpp

#include "observer.h"
#include <iostream>
int main()
{ConcreteSubject *subject = new ConcreteSubject;subject->Add(new ConcreteObserver(subject,"TMG"));subject->Add(new ConcreteObserver(subject,"WYA"));subject->setSubjectStatus(subject,"在线");std::cout<<std::endl;delete subject;
}

更多资料点击 GitHub 欢迎各位读者去Star

⭐学术交流群Q 754410389 持续更新中~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/138304.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Twitter图片数据优化的细节

Twitter个人数据优化&#xff1a;吸引更多关注和互动 头像照片在Twitter上&#xff0c;头像照片是最快识别一个账号的方法之一。因此&#xff0c;请务必使用公司的标志或与品牌相关的图片。建议尺寸为400x400像素。 为了建立强大的品牌形象和一致性&#xff0c;强烈建议在所有…

Spring MVC常见面试题

Spring MVC简介 Spring MVC框架是以请求为驱动&#xff0c;围绕Servlet设计&#xff0c;将请求发给控制器&#xff0c;然后通过模型对象&#xff0c;分派器来展示请求结果视图。简单来说&#xff0c;Spring MVC整合了前端请求的处理及响应。 Servlet 是运行在 Web 服务器或应用…

Xcode 15 运行<iOS 14, 启动崩溃问题

如题. Xcode 15 启动 < iOS 14(没具体验证过, 我的问题设备是iOS 13.7)真机设备 出现启动崩溃 解决方案: Build Settings -> Other Linker Flags -> Add -> -ld64

第八天:gec6818arm开发板和Ubuntu中安装并且编译移植mysql驱动连接QT执行程序

一、Ubuntu18.04中安装并且编译移植mysql驱动程序连接qt执行程序 1 、安装Mysql sudo apt-get install mysql-serverapt-get isntall mysql-clientsudo apt-get install libmysqlclient-d2、查看是否安装成功&#xff0c;即查看MySQL版本 mysql --version 3、MySQL启动…

STP生成树协议基本配置示例---STP逻辑树产生和修改

STP是用来避免数据链路层出现逻辑环路的协议&#xff0c;运行STP协议的设备通过交互信息发现环路&#xff0c;并通过阻塞特定端口&#xff0c;最终将网络结构修剪成无环路的树形结构。在网络出现故障的时候&#xff0c;STP能快速发现链路故障&#xff0c;并尽快找出另外一条路径…

Selenium-介绍下其他骚操作

Chrome DevTools 简介 Chrome DevTools 是一组直接内置在基于 Chromium 的浏览器&#xff08;如 Chrome、Opera 和 Microsoft Edge&#xff09;中的工具&#xff0c;用于帮助开发人员调试和研究网站。 借助 Chrome DevTools&#xff0c;开发人员可以更深入地访问网站&#xf…

SpringMVC初级

文章目录 一、SpringMVC 概述二、springMVC步骤1、新建maven的web项目2、导入maven依赖3、创建controller4、创建spring-mvc.xml配置文件&#xff08;本质就是spring的配置件&#xff09;5、web.xml中配置前端控制器6、新建a.jsp文件7、配置tomcat8、启动测试 三、工作流程分析…

【Vue】如何搭建SPA项目--详细教程

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《Spring与Mybatis集成整合》《springMvc使用》 ⛺️ 生活的理想&#xff0c;为了不断更新自己 ! 目录 1.什么是vue-cli 2.安装 2.1.创建SPA项目 2.3.一问一答模式答案 3.运行SPA项目 3…

UML活动图

在UML中&#xff0c;活动图本质上就是流程图&#xff0c;它描述系统的活动、判定点和分支等&#xff0c;因此它对开发人员来说是一种重要工具。 活动图 活动是某件事情正在进行的状态&#xff0c;既可以是现实生活中正在进行的某一项工作&#xff0c;也可以是软件系统中某个类…

【element-ui】form表单动态修改rules校验项

在项目开发过程中&#xff0c;该页面有暂存和提交两个按钮&#xff0c;其中暂存和提交必填项校验不一样&#xff0c;此时需要动态增减必填项校验 &#xff0c;解决方法如下&#xff1a; 增加rules校验项 this.$set(this.formRules,name,[{required:true,message:请输入名称,t…

润和软件HopeStage与华宇信息TAS应用中间件完成产品兼容性互认证

近日&#xff0c;江苏润和软件股份有限公司&#xff08;以下简称“润和软件”&#xff09;HopeStage 操作系统与北京华宇信息技术有限公司&#xff08;以下简称“华宇信息”&#xff09;TAS应用中间件软件完成产品兼容性测试。 测试结果表明&#xff0c;企业级通用操作系统Hope…

【Windows Server 2012 R2搭建FTP站点】

打开服务器管理器——添加角色和功能 下一步 下一步 下一步 选择FTP服务器&#xff0c;勾上FTP服务和FTP扩展&#xff0c;点击下一步 安装 安装完成关闭 打开我们的IIS服务器 在WIN-XXX主页可以看到我们的FTP相关菜单 右键WIN-XXXX主页&#xff0c;添加FTP站点 输入站点名称-FT…

前端面试手撕编程之ES+算法

目录 ES6 防抖 节流 防抖、节流应用 改变this call typeof this ! function context context || window context._this this delete context._this bind&#xff1a; return _this.apply(context, [...arguments].slice(1)); 深拷贝 !arr|| arr null || typeo…

【分布式计算】七、同步 synchronization 重难点

两个协议&#xff1a; 1、NTP&#xff08;Network Time Protocal)–>广泛使用    机器周期向时间服务器获取准确时间   2、没有协议名称 − > -> −>没有广泛使用    时间服务器周期扫描所有机器&#xff0c;计算时间平均值&#xff1b;导致时间服务器负载…

【数据结构】时间、空间复杂度

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;浅谈数据结构 &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 时间、空间复杂度 1. 算法效率3. 时…

应用程序处理:TCP模块的处理

1、应用程序处理 首先应用程序会进行编码处理&#xff0c;这些编码相当于 OSI 的表示层功能&#xff1b; 编码转化后&#xff0c;邮件不一定马上被发送出去&#xff0c;这种何时建立通信连接何时发送数据的管理功能&#xff0c;相当于 OSI 的会话层功能。 2、TCP 模块的处理 …

Acer宏碁暗影骑士5笔记本AN517-54原装出厂Win10系统工厂模式

宏基电脑原厂WINDOWS10系统自带所有硬件的驱动、NITROSENSE风扇键盘控制中心、Office办公软件、出厂主题壁纸LOGO、 Acer Care Center、Quick Access等预装程序 链接&#xff1a;https://pan.baidu.com/s/1Ovui_CvsUaF-TX0NbuhEVg?pwdcrmv 提取码&#xff1a;crmv 所需要工…

Hadoop-sqoop

sqoop 1. Sqoop简介及原理 简介&#xff1a; Sqoop是一款开源的工具,主要用于在Hadoop(Hive)与传统的数据库(mysq1.postgresql..)间进行数据的传递&#xff0c;可以将一个关系型数据库&#xff08;例如: MySQL ,Oracle ,Postgres等&#xff09;中的数据导进到Hadoop 的HDFS中&…

2、Window上的 虚拟机端口 暴露到 宿主机局域网教程

今天在公司的服务器主机上捣鼓虚拟机&#xff0c;要在虚拟机上安装一个oracle&#xff0c;虚拟机和主机能互相ping通的前提下&#xff0c;要将虚拟机上的端口号暴露在主机上&#xff0c;让项目组内的所有员工的电脑都能访问到该oracle数据库。 也就是电脑A 访问主机&#xff0…

计算机网络运维方向综合知识大全

一. 基础知识 1. 网络的组成 组成部分&#xff1a;硬件、软件、协议 硬件主要由主机&#xff08;也称端系统&#xff09;、通信链路&#xff08;如双绞线、光纤&#xff09;、交换设备&#xff08;如路由器、交换机等)和通信处理机&#xff08;如网卡)等组成。软件主要包括各种…