热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

设计模式C++观察者模式

无论是在现实世界中还是在软件系统中,人们常常会遇到这样一类问题,一个对象的状态改变会引发其他对象的状态改变,如十字路口的交通信号灯,红灯亮则汽车停,绿灯亮则汽车行,再如点击软件中一

无论是在现实世界中还是在软件系统中,人们常常会遇到这样一类问题,一个对象的状态改变会引发其他对象的状态改变,如十字路口的交通信号灯,红灯亮则汽车停,绿灯亮则汽车行,再如点击软件中一个按钮,则会弹出一个窗口。这些对象之间存在一种依赖关系,一个对象的行为会导致依赖它的其他对象发生反应,为了更好地描述这种对象之间的依赖关系,我们需要学习一种新的行为型设计模式,即观察者模式,它是软件设计与开发中使用频率最高的设计模式之一

定义思想:定义对象间一种一对多的依赖关系,使得每当一个对象状态发生改变时,其他相关对象皆得到通知并自动更新

优点:


  1. 实现了表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制
  2. 观察者模式支持广播通信,观察目标会向所有注册的观察者发出通知,简化了一对多系统设计的难度
  3. 观察者模式符合开闭原则的要求,增加新的具体观察者无须修改原有系统代码

缺点:


  1. 如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间
  2. 如果观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃

适用场景:


  1. 一个对象必须通知其他对象,而并不知道这些对象时谁
  2. 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,降低了对象之间的耦合度
    案例:3个英雄打1个怪兽,当怪兽挂掉时需要通知所有英雄,当一个英雄阵亡时不需要通知。

代码:

//抽象的英雄
class AbstractOHero
{
public:virtual void Update() = 0;
};class HeroA : public AbstractOHero
{
public:HeroA(){cout << "英雄A正在打怪兽" << endl;}virtual void Update(){cout << "英雄A停止打怪兽" << endl;}
};class HeroB : public AbstractOHero
{
public:HeroB(){cout << "英雄B正在打怪兽" << endl;}virtual void Update(){cout << "英雄B停止打怪兽" << endl;}
};class HeroC : public AbstractOHero
{
public:HeroC(){cout << "英雄C正在打怪兽" << endl;}virtual void Update(){cout << "英雄C停止打怪兽" << endl;}
};//抽象的观察目标
class AbstractBoss
{
public://添加观察者virtual void addHero(AbstractOHero* hero) &#61; 0;//删除观察者virtual void deleteHero(AbstractOHero* hero) &#61; 0;//通知观察者virtual void notify() &#61; 0;
};//具体的观察者 BossA
class BossA : public AbstractBoss
{
public://添加观察者virtual void addHero(AbstractOHero* hero){pHeroList.push_back(hero);}//删除观察者virtual void deleteHero(AbstractOHero* hero){pHeroList.remove(hero);}//通知观察者virtual void notify(){for (const auto& e : pHeroList){e->Update();}}
private:list<AbstractOHero*> pHeroList;
};

测试&#xff1a;

void test()
{//创建观察者AbstractOHero* heroA &#61; new HeroA();AbstractOHero* heroB &#61; new HeroB();AbstractOHero* heroC &#61; new HeroC();//创建观察目标AbstractBoss* bossA &#61; new BossA();bossA->addHero(heroA);bossA->addHero(heroB);bossA->addHero(heroC);cout << "heroC挂了" << endl;bossA->deleteHero(heroC);cout << "Boss死了&#xff0c;通知其英雄" << endl;bossA->notify();delete heroA;delete heroB;delete heroC;delete bossA;
}

运行截图&#xff1a;
在这里插入图片描述


推荐阅读
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • vue使用
    关键词: ... [详细]
  • 电话号码的字母组合解题思路和代码示例
    本文介绍了力扣题目《电话号码的字母组合》的解题思路和代码示例。通过使用哈希表和递归求解的方法,可以将给定的电话号码转换为对应的字母组合。详细的解题思路和代码示例可以帮助读者更好地理解和实现该题目。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了在Vue项目中如何结合Element UI解决连续上传多张图片及图片编辑的问题。作者强调了在编码前要明确需求和所需要的结果,并详细描述了自己的代码实现过程。 ... [详细]
  • 006_Redis的List数据类型
    1.List类型是一个链表结构的集合,主要功能有push,pop,获取元素等。List类型是一个双端链表的结构,我们可以通过相关操作进行集合的头部或者尾部添加删除元素,List的设 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • 本文详细介绍了git常用命令及其操作方法,包括查看、添加、提交、删除、找回等操作,以及如何重置修改文件、抛弃工作区修改、将工作文件提交到本地暂存区、从版本库中删除文件等。同时还介绍了如何从暂存区恢复到工作文件、恢复最近一次提交过的状态,以及如何合并多个操作等。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
author-avatar
入骨红豆撕不撕
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有