文章目录

  • 常见设计模式之(五):观察者模式
    • 1 什么是观察者模式(observer pattern)?
      • 1.1 定义
      • 1.2 观察者模式中角色
    • 2、观察者模式的c++实现
    • 3 观察者模式的应用
      • 3.1 观察者模式的注意事项
        • 广播链问题
        • 程序效率
      • 3.2 实际项目中具体应用
    • 4 观察者模式的扩展
      • 4.1 项目中真实的观察模式
        • 4.1.1 观者者和被观察者之间的沟通机制
        • 4.1.2 观察者响应
      • 4.1.3 被观察者选择通知的人
      • 4.1.4 观察者和被观察者的扩展
      • 4.2 观者模式的终极boss (订阅-发布模式)

常见设计模式之(五):观察者模式

1 什么是观察者模式(observer pattern)?

1.1 定义

摘自 java 设计模式官网 中 有关观察者模式的定义:

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically

翻译一下:
定义这样一种一对多的关系:当一个对象状态改变时,所有依赖这个对象的都会得到通知并且自动更新。

1.2 观察者模式中角色

角色 职责
被观察者(subject) 1. 动态地增加、取消观察者;2、发生改变时通知观察者 3、一般为抽象类
具体观察者(ConcreteSubject) 1. 实现自己的业务逻辑(比如说获取串口数据等)2、定义对哪些事件进行通知
观察者(Observer) 1、收到Update时,对收到的信息进行处理
具体观察者(ConcreteObserver) 1、对于不同的具体的观察者,对于信息的处理是不一样的 ,每个具体的观者都有自己的处理逻辑

2、观察者模式的c++实现

本博文先介绍观察者模式最简单模型,一般通用的类图如下:

c++源码如下:

AbstractSubject.h

#ifndef ABSTRACT_SUBJECT_H
#define ABSTRACT_SUBJECT_H
#include <stdio.h>
#include <vector>#include "AbstractObserver.h"
class AbstractObserver;
class AbstractSubject
{
public :AbstractSubject(){}~AbstractSubject(){}void add_observer(AbstractObserver * observer){vec_observer.push_back(observer);}void delete_observer(AbstractObserver  * observer){for(auto intor = vec_observer.begin();intor != vec_observer.end();intor++){if(*intor == observer){vec_observer.erase(intor);}}}void notify_all_observer(void){for(auto intor = vec_observer.begin();intor != vec_observer.end();intor++){(*intor) ->update();}}private:std::vector< AbstractObserver *> vec_observer;};#endif

AbstractObserver.h

#ifndef ABSTRACT_OBSERVER_H
#define ABSTRACT_OBSERVER_H
#include <stdio.h>
#include <vector>class AbstractObserver
{
public :AbstractObserver(){}~AbstractObserver(){}virtual void update(void) = 0;
};#endif

ConcreteSubject.h

#ifndef CONCRETE_SUBJECT_H
#define CONCRETE_SUBJECT_H
#include <stdio.h>#include "AbstractSubject.h"class ConcreteSubject : public AbstractSubject
{
public:ConcreteSubject(){}~ConcreteSubject(){}void do_some_thing(void){printf("ConcreteSubject %s %d \n",__FUNCTION__,__LINE__);notify_all_observer();  }
};
#endif

ConcreteObserver1.h

#ifndef CONCRETE_OBSERVER_1_H
#define CONCRETE_OBSERVER_1_H#include "AbstractObserver.h"class ConcreteObserver1 :public AbstractObserver
{
public:ConcreteObserver1(){}~ConcreteObserver1(){}virtual void update(void) override{printf("%s %s %d \n",__FILE__,__FUNCTION__,__LINE__);}};#endif

ConcreteObserver2.h

#ifndef CONCRETE_OBSERVER_2_H
#define CONCRETE_OBSERVER_2_H#include "AbstractObserver.h"class ConcreteObserver2 :public AbstractObserver
{
public:ConcreteObserver2(){}~ConcreteObserver2(){}virtual void update(void) override{printf("%s %s %d \n",__FILE__,__FUNCTION__,__LINE__);}};#endif

ConcreteObserver3.h

#ifndef CONCRETE_OBSERVER_3_H
#define CONCRETE_OBSERVER_3_H
#include "AbstractObserver.h"
class ConcreteObserver3 :public AbstractObserver
{
public:ConcreteObserver3(){}~ConcreteObserver3(){}virtual void update(void) override{printf("%s %s %d \n",__FILE__,__FUNCTION__,__LINE__);}
};
#endif

ObserverClient.cpp

#include "AbstractSubject.h"
#include "AbstractObserver.h"#include "ConcreteObserver1.h"
#include "ConcreteObserver2.h"
#include "ConcreteObserver3.h"#include "ConcreteSubject.h"int main(void)
{// 定义一个被观察者AbstractSubject * pcls_subject = new ConcreteSubject();// 定义三个观察者AbstractObserver * co1 = new ConcreteObserver1();AbstractObserver * co2 = new ConcreteObserver2();AbstractObserver * co3 = new ConcreteObserver3();//添加三个观察者pcls_subject->add_observer(co1);pcls_subject->add_observer(co2);pcls_subject->add_observer(co3);// 被观察者状态改变pcls_subject->notify_all_observer();pcls_subject->delete_observer(co2);pcls_subject->notify_all_observer();delete co1;delete co2;delete co3;delete pcls_subject;
}

编译并运行如下:

root@wan:/wan/06Observer# g++ -o ObserverClient ObserverClient.cpp -std=c++11 -g
root@wan:/wan/06Observer# ./ObserverClient
ConcreteObserver1.h update 22
ConcreteObserver2.h update 22
ConcreteObserver3.h update 22
ConcreteObserver1.h update 22
ConcreteObserver3.h update 22

3 观察者模式的应用

3.1 观察者模式的注意事项

广播链问题

在观察者模式中一个观察者可以拥有双重身份,既是观察者,也是观察者,这就意味着:A -> B ->C 一旦建立这样的广播链,会造成程序负担。如果不慎就会广播风暴

程序效率

在存在多级触发时会存在程序的效率问题。

3.2 实际项目中具体应用

  • 文件系统 :比如说 我们建立了一个新文件,在建立文件的同时需要通知 磁盘管理 目录管理器等程序
  • 生活中的收音机
  • ATM机:当我们取完钱时:通知短信系统、余额更新系统等

4 观察者模式的扩展

4.1 项目中真实的观察模式

上述例子是非常原始的观察者模式,而在我们实际的项目中不会存在这样纯粹的模式,在系统设计中会对观察者中各个角色进行改造。

4.1.1 观者者和被观察者之间的沟通机制

被观察者状态改变会触发观察者的一个行为,同时会传递一个消息。这样就存在两个问题:如何通知给观者者,传递的消息的形式。

  1. 如何传递:
    观者和被观察者可以通过以下技术传递消息:消息队列、共享内存、管道、网络、硬件总线等,大家在进行系统设计时可以根据自己的情况进行选择。
  2. 消息传递格式:
    常见的消息格式有以下几种:json xml protobuf 自定义数据格式等。

4.1.2 观察者响应

观察者在既要接受被观察者传递过来的消息,同时还要处理相关消息,在观察者要处理N个被观察者传递过来的消息时,观察者就需要考虑自己的响应效率,一般两种方案:

1.空间换时间
采用缓存技术,准备好足够的空间来缓存消息,我先将消息缓存下来,然后自己慢慢处理,我只需要保证及时、快速地响应就可以了。
2.利用多线程技术
增加线程的数量,增强自己系统能力。

4.1.3 被观察者选择通知的人

在实际的项目中,存在这样问题,被观察者可能不需要传递给所有人,只需要传递给那些对消息感兴趣的的人,这点有点像网络中 广播 组播 单播 。被观察者自己决定传递给哪些人。做系统设计时需要考虑这个问题,保证架构的灵活性。

4.1.4 观察者和被观察者的扩展

首先是角色的变化:
双重身份的角色的存在。一个观察者同样也可以是被观察者。
数量的变化:
多个观察者 多个被观察者。

4.2 观者模式的终极boss (订阅-发布模式)

通过上面对观察者模式的扩展,最终扩展为订阅-发布的模式,想想生活中这样的例子太多了:手机消息的推送、公众号的订阅等等。在我们实际的开发中也存在一些订阅-发布模式的开源工具:比如说 mqtt zeromq nanomq等工具都支持订阅发布,在后续博文中我们将以mqtt为例来讲述订阅发布在实际项目中的应用。

常见设计模式之(五):观察者模式相关推荐

  1. 设计模式 ( 十六 ) 观察者模式Observer(对象行为型)

    设计模式 ( 十五 ) 观察者模式Observer(对象行为型) 1.概述 一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力.当对象们连接在一起时,它们就可以相互提供服务和信息. 通常来 ...

  2. 设计模式(五)观察者模式

    相关文章 设计模式系列 1.观察者模式模式简介 定义 观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时 ...

  3. JavaScript 中常见设计模式整理

    开发中,我们或多或少地接触了设计模式,但是很多时候不知道自己使用了哪种设计模式或者说该使用何种设计模式.本文意在梳理常见设计模式的特点,从而对它们有比较清晰的认知. JavaScript 中常见设计模 ...

  4. 设计模式(五)适配器模式Adapter(结构型)

    设计模式(五)适配器模式Adapter(结构型) 1. 概述: 接口的改变,是一个需要程序员们必须(虽然很不情愿)接受和处理的普遍问题.程序提供者们修改他们的代码;系统库被修正;各种程序语言以及相关库 ...

  5. Java 10种常见设计模式UML图

    Java 10种常见设计模式UML图 简单工厂模式(不属于23种设计模式) 工厂方法模式 单例 模式(静态内部类方式 IODH) 适配器模式 装饰者模式 门面模式 代理模式(静态代理) 观察者模式 策 ...

  6. Java实现二十三种设计模式(五)—— 十一种行为型模式 (中)——解释器模式、迭代器模式、中介者模式、备忘录模式

    Java实现二十三种设计模式(五)-- 十一种行为型模式 (中)--解释器模式.迭代器模式.中介者模式.备忘录模式 一.解释器模式 我国 IT 界历来有一个汉语编程梦,虽然各方对于汉语编程争论不休,甚 ...

  7. 小菜学习设计模式(五)—控制反转(Ioc)

    写在前面 设计模式目录: 小菜学习设计模式(一)-模板方法(Template)模式 小菜学习设计模式(二)-单例(Singleton)模式 小菜学习设计模式(三)-工厂方法(Factory Metho ...

  8. 设计模式(五)——建造者模式

    设计模式(五)--建造者模式 一.建造者模式简介 1.建造者模式简介 建造者模式将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示. 建造者模式和抽象工厂模式在功能上很相似,都是用来 ...

  9. java面试常见设计模式

    java面试常见设计模式 看这里,动画描述很好 创建型模式 工厂方法模式 目的 结构 场景 优缺点 示例代码 button factory Demo.java: 客户端代码 抽象工厂模式 目的 结构 ...

  10. Android常见设计模式——代理模式(Proxy Pattern)(二)

    文章目录 1. 前言 2. 远程代理(Remote Proxy) 3. 后记 1. 前言 在上篇Android常见设计模式--代理模式(Proxy Pattern)中基本上知道了什么是代理模式,以及对 ...

最新文章

  1. UML类图新手入门级介绍
  2. STARTUP报错:ORA-00205: error in identifying control file, check alert log for more info
  3. GAN性能不稳?这九大技术可“镇住”四类缺陷
  4. java怎么加定时器_JAVA WEB程序中添加定时器
  5. 图神经网络 | BrainGNN: 用于功能磁共振成像分析的可解释性脑图神经网络
  6. 空except的慎用
  7. 关于Anaconda的环境和包管理
  8. 基于web的工作流设计器(多比图形控件)
  9. 【Java】七巧板着色问题
  10. php通过使用curl获取http或者https的响应信息的方式
  11. 微软:SolarWinds 供应链攻击事件幕后黑手攻击全球24国政府
  12. 决定明智地放弃对名手旋风等象棋引擎的破解...
  13. UISwitch的使用 - IOS
  14. 基于MPC5748G的以太网展板通信模块解析
  15. Invalid interval string, expecting a number followed by one of Mwdhmsy
  16. 工作表冻结前两行_冻结所有工作表宏
  17. iOS开发实战细节——通知写法
  18. python中imag是什么意思_Python-在imag中查找主要/最常见的颜色
  19. 2017中国云计算评测报告 1
  20. 电源管理之pmu驱动分析

热门文章

  1. 使用wps把word格式文件转换成pdf文件
  2. 闲人闲谈PS之十五——合同、项目、WBS的关系
  3. 简单了解冯·诺依曼体系结构
  4. 制作U盘PE启动盘安装Windows系统
  5. Xcode Message from debugger: Terminated due to memory issue
  6. 七夕祝福网页制作_七夕福利 | 程序员土味情话大PK,专属好礼等你拿
  7. Rayman的绝顶之路——Leetcode每日一题打卡10
  8. Caused by: java.lang.SecurityException: Neither user 10068 nor current process has android.permissio
  9. 关于短期培训月薪过万的悖论
  10. 城市生态规划关键技术方法之六:情景分析方法