代码写的不够规范,目的是缩短篇幅,实际情况请不要这样做

1、概述

  观察者模式,类比生活中的场景,比如看电影,观众对播放的内容有不同的反应, 再比如订阅,公众号订阅,只要你订阅了其公众号,你就会收到其推送。再比如,天气,人们针对天气变化的反应也是不一样的。

  观察者模式的主要角色如下。
  A、抽象主题角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
  B、具体主题角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
  C、抽象观察者角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
  D、具体观察者角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。

  总结,主要2个对象: 观察者和被观察对象。

2、观察者抽象类

// 观察者
class observer
{
public:
// 观察者的反应
virtual void respond() = 0;
};

3、观察者类

  这里,准备了两个观察者,

// 观察者A
class observerA : public observer
{
public:
void respond()
{
std::cout << "\n观察者A做出反应\n";
}
}; // 观察者B
class observerB : public observer
{
public:
void respond()
{
std::cout << "\n观察者B做出反应\n";
}
};

4、抽象对象(目标)

// 抽象目标
class subject
{
public:
// 添加新的观察者
virtual void add(observer *pobs)
{
if (!pobs)
return; std::list<observer*>::iterator it = std::find(_plist_observer.begin(), _plist_observer.end(), pobs); // 没有找到,则添加
if (it == _plist_observer.end())
_plist_observer.push_back(pobs);
else
cout << "\n对象已经存在,无需重复添加\n"; } // 删除观察者
virtual void remove(observer *pobs)
{
if (!pobs)
return; int size = _plist_observer.size();
if (0 < size)
_plist_observer.remove(pobs);
} // 通知所有观察者
virtual void notify_observer() = 0; protected:
// 可能有多个观察者
std::list<observer*> _plist_observer;
};

5、具体目标类

// 对象A,
class subjectA :public subject
{
public:
// 实现,并通知观察者
void notify_observer()
{
std::cout << "\n\n\n-----请注意,目标A已经变化了----\n";
for each (auto item in _plist_observer)
item->respond();
}
};

6、调用示例

 1 // 调用
2 void call_observer()
3 {
4 // 1、创建观察者 和 被观察的目标
5 std::unique_ptr<observer> pobsA(new(std::nothrow) observerA);
6 std::unique_ptr<observer> pobsB(new(std::nothrow) observerB);
7 std::unique_ptr<subject> psubA(new(std::nothrow) subjectA);
8
9 if (!pobsA || !pobsB || !psubA)
10 {
11 std::cout << "\n 创建观察者或者目标失败\n\n";
12 return;
13 }
14
15 // 2、被观察目标添加观察者
16 psubA->add(pobsA.get());
17 psubA->add(pobsB.get());
18 std::cout << "1、目标变化了,观察者反应:";
19 psubA->notify_observer();
20
21 // 3、解除观察者
22 psubA->remove(pobsA.get());
23 std::cout << "\n\n2、解除观察者A,目标变化,观察者反应";
24 psubA->notify_observer();
25 }

7、输出

c++设计模式概述之观察者的更多相关文章

  1. java设计模式概述

    java的设计模式大体上分为三大类: 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式. 结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模 ...

  2. 23种GoF设计模式概述

    23种GoF设计模式概述 在前面,我们对 GoF 的 23 种设计模式进行了分类,这里先对各个设计模式的功能进行简要介绍,以便有个大概了解.后面的章节再进行详细介绍. 创建型模式 关注于怎么创建对象的 ...

  3. Java设计模式(一):设计模式概述、UML图、设计原则

    1 设计模式概述 1.1 软件设计模式的产生背景 "设计模式"最初并不是出现在软件设计中,而是被用于建筑领域的设计中. 1977年美国著名建筑大师.加利福尼亚大学伯克利分校环境结构 ...

  4. 设计模式(一)----设计模式概述及UML图解析

    1.设计模式概述 1.1 软件设计模式的产生背景 "设计模式"最初并不是出现在软件设计中,而是被用于建筑领域的设计中. 1977年美国著名建筑大师.加利福尼亚大学伯克利分校环境结构 ...

  5. java 28 - 1 设计模式 之 面向对象思想设计原则和模版设计模式概述

    在之前的java 23 中,了解过设计模式的单例模式和工厂模式.在这里,介绍下设计模式 面向对象思想设计原则 在实际的开发中,我们要想更深入的了解面向对象思想,就必须熟悉前人总结过的面向对象的思想的设 ...

  6. OOAD-设计模式(二)之GRASP模式与GOF设计模式概述

    一.GRASP模式(通用责任分配软件模式)概述 1.1.理解责任 1)什么是责任 责任是类间的一种合约或义务,也可以理解成一个业务功能,包括行为.数据.对象的创建等 知道责任——表示知道什么 行为责任 ...

  7. PHP设计模式概述

    PHP设计模式概述 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. ...

  8. 【OOAD】设计模式概述

    模式的诞生与定义 模式起源于建筑业而非软件业模式(Pattern)之父——美国加利佛尼亚大学环境结构中心研究所所长Christopher Alexander博士<A Pattern Langua ...

  9. 系统架构-设计模式(适配器、观察者、代理、抽象工厂等)及架构模式(C/S、B/S、分布式、SOA、SaaS)(干货)

    博客园首页是需要分享干货的地方,今天早上写的<HRMS(人力资源管理系统)-从单机应用到SaaS应用-系统介绍>内容下架了,所以我就按照相关规定,只分享干货,我把之前写完的内容整理发布上来 ...

随机推荐

  1. LG 11 月 月赛 II T4

    LG 11 月 月赛 II T4 看到膜数和 $ 10^5 $ 以及 $ n^2 $ 的部分分想到很可能是 NTT 于是开始推式子 首先看到式子可以化作, 如果 \(k = 0\) , $ f(l , ...

  2. Linux图片查看软件ImageMagick安装

    在Linux中查看图片,这个需求是非常常见的.总不至于在集群中生成个图片,随便看下效果,也要用filezilla.winscp之类的远程文件传输工具导过来导过去吧,这样效率太低. Linux图片查看常 ...

  3. 认识Influxdb时序数据库及Influxdb基础命令操作

    认识Influxdb时序数据库及Influxdb基础命令操作 一.什么是Influxdb,什么又是时序数据库 Influxdb是一个用于存储时间序列,事件和指标的开源数据库,由Go语言编写而成,无需外 ...

  4. 详解工作流框架Activiti的服务架构和组件

    摘要:通过这篇文章,可以对工作流有一个基本的认识,为后续工作流框架Activiti的学习打下坚实的基础. 本文分享自华为云社区<BPMN工作流的基本概念!详解工作流框架Activiti的服务架构 ...

  5. 表格table的宽度问题

    首先注意table的一个样式 table { table-layout:fixed; } table-layout有以下取值: automatic 默认.列宽度由单元格内容设定 fixed 列宽由表格 ...

  6. MySQL全面瓦解29:使用Partition功能实现水平分区

    1 回顾 上一节我们详细讲解了如何对数据库进行分区操作,包括了 垂直拆分(Scale Up 纵向扩展)和 水平拆分(Scale Out 横向扩展) ,同时简要整理了水平分区的几种策略,现在来回顾一下. ...

  7. TD课程通最终版本体验

    功能上,新版本增加了学校教室的上课情况,有无课程可以清楚查询,如下图: 在添加课程的设置上有改进,相比于之前编辑课程后不能保存,新版本在可保存的基础上又增加了登陆教务系统的功能,学生使用更加方便快捷, ...

  8. MapReduce04 框架原理Shuffle

    目录 2 MapReduce工作流程 3 Shuffle机制(重点) 3.1 Shuffle机制 3.2 Partition分区 默认Partitioner分区 自定义Partitioner分区 自定 ...

  9. 位运算符在JS中的妙用

    正文 位运算 JavaScript 中最臭名昭著的 Bug 就是 0.1 + 0.2 !== 0.3,因为精度的问题,导致所有的浮点运算都是不安全的,具体原因可详见<0.1 + 0.2不等于0. ...

  10. 转 【Android】- Android与html5交互操作

    转自:https://blog.csdn.net/baidu_35701759/article/details/70314812 1. Android提供了WebView控件可访问网页 通过webVi ...