【设计模式】观察者模式

2023-10-27

观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新。

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。

介绍

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

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

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

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

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

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

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

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

使用场景:

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

注意事项: 1、JAVA 中已经有了对观察者模式的支持类。 2、避免循环引用。 3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。

观察者模式包含以下几个核心角色:

  • 主题(Subject):也称为被观察者或可观察者,它是具有状态的对象,并维护着一个观察者列表。主题提供了添加、删除和通知观察者的方法。
  • 观察者(Observer):观察者是接收主题通知的对象。观察者需要实现一个更新方法,当收到主题的通知时,调用该方法进行更新操作。
  • 具体主题(Concrete Subject):具体主题是主题的具体实现类。它维护着观察者列表,并在状态发生改变时通知观察者。
  • 具体观察者(Concrete Observer):具体观察者是观察者的具体实现类。它实现了更新方法,定义了在收到主题通知时需要执行的具体操作。

观察者模式通过将主题和观察者解耦,实现了对象之间的松耦合。当主题的状态发生改变时,所有依赖于它的观察者都会收到通知并进行相应的更新。

实现

观察者模式使用三个类 Subject、Observer 和 Client。Subject 对象带有绑定观察者到 Client 对象和从 Client 对象解绑观察者的方法。我们创建 Subject 类、Observer 抽象类和扩展了抽象类 Observer 的实体类。

ObserverPatternDemo,我们的演示类使用 Subject 和实体类对象来演示观察者模式。

观察者模式的 UML 图

步骤 1

创建 Subject 类。

Subject.java

import java.util.ArrayList;
import java.util.List;
 
public class Subject {
   
   private List<Observer> observers 
      = new ArrayList<Observer>();
   private int state;
 
   public int getState() {
      return state;
   }
 
   public void setState(int state) {
      this.state = state;
      notifyAllObservers();
   }
 
   public void attach(Observer observer){
      observers.add(observer);      
   }
 
   public void notifyAllObservers(){
      for (Observer observer : observers) {
         observer.update();
      }
   }  
}

步骤 2

创建 Observer 类。

Observer.java

public abstract class Observer {
   protected Subject subject;
   public abstract void update();
}

步骤 3

创建实体观察者类。

BinaryObserver.java

public class BinaryObserver extends Observer{
 
   public BinaryObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }
 
   @Override
   public void update() {
      System.out.println( "Binary String: " 
      + Integer.toBinaryString( subject.getState() ) ); 
   }
}

OctalObserver.java

public class OctalObserver extends Observer{
 
   public OctalObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }
 
   @Override
   public void update() {
     System.out.println( "Octal String: " 
     + Integer.toOctalString( subject.getState() ) ); 
   }
}

HexaObserver.java

public class HexaObserver extends Observer{
 
   public HexaObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }
 
   @Override
   public void update() {
      System.out.println( "Hex String: " 
      + Integer.toHexString( subject.getState() ).toUpperCase() ); 
   }
}

步骤 4

使用 Subject 和实体观察者对象。

ObserverPatternDemo.java

public class ObserverPatternDemo {
   public static void main(String[] args) {
      Subject subject = new Subject();
 
      new HexaObserver(subject);
      new OctalObserver(subject);
      new BinaryObserver(subject);
 
      System.out.println("First state change: 15");   
      subject.setState(15);
      System.out.println("Second state change: 10");  
      subject.setState(10);
   }
}

步骤 5

执行程序,输出结果:

First state change: 15
Hex String: F
Octal String: 17
Binary String: 1111
Second state change: 10
Hex String: A
Octal String: 12
Binary String: 1010

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【设计模式】观察者模式 的相关文章

  • Chain of Responsibility:责任链模式

    现有多个处理者 这些处理者可以处理不同的请求 这些处理者有等级关系 每个处理者都有更上级的处理者 对于最上级的处理者 可以没有上级 对于一个上级处理者 可以有多个下级处理者 客户端发出了一个请求 请求被传递给一个最下级处理者 而该处理者无法
  • 设计模式的 C++ 实现---原型模式

    前文回顾 单例模式 一 单例模式 二 观察者模式 简单工厂模式 工厂方法模式 一 工厂方法模式 二 抽象工厂模式 一 抽象工厂模式 二 前言 原型模式指直接用一个已经存在的对象来创建一个新的对象 然后对新对象进行稍微修改即可 类似复制的操作
  • 23种设计模式之装饰模式

    装饰模式 一个简陋的房子 它可以让人在里面居住 为人遮风避雨 但如果给它进行装修 那么它的居住环境就更加宜人了 程序中的对象也与房子十分类似 首先有一个相当于 房子 的对象 然后经过不断装饰 不断对其增加功能 它就变成了使用功能更加强大的对
  • 设计模式-单一职责原则介绍与理解

    描述 一个类应该专注于实现一个功能 好处 便于代码复用 举例 俄罗斯方块游戏 首先可以想到的是游戏逻辑与界面的分离 也就是说逻辑一个类 界面部分一个类 这样做的好处就是我们可以复用游戏逻辑的代码 例如我们用java写了一个基于PC端的俄罗斯
  • 设计模式三: 代理模式(Proxy) -- JDK的实现方式

    简介 代理模式属于行为型模式的一种 控制对其他对象的访问 起到中介作用 代理模式核心角色 真实角色 代理角色 按实现方式不同分为静态代理和动态代理两种 意图 控制对其它对象的访问 类图 实现 JDK自带了Proxy的实现 下面我们先使用JD
  • 行为型模式-策略模式

    package per mjn pattern strategy 抽象策略类 public interface Strategy void show package per mjn pattern strategy 具体策略类 用来封装算法
  • 设计模式之(三)---工厂方法模式

    女娲补天的故事大家都听过吧 这个故事是说 女娲在补了天后 下到凡间一看 哇塞 风景太优美了 天空是湛 蓝的 水是清澈的 空气是清新的 太美丽了 然后就待时间长了就有点寂寞了 没有动物 这些看的到 都是静态的东西呀 怎么办 别忘了是神仙呀 没
  • C++ 装饰器模式

    什么是装饰器模式 装饰器模式是一种结构型设计模式 实现了在不改变现有对象结构的的同时又拓展了新的功能 装饰器本质上是对现有对象的重新包装 同时装饰器又称为封装器 如何理解装饰器模式 以笔记本电脑为例 当我们购买了一台新笔记本电脑 但我们发现
  • 设计模式之享元模式

    一 背景 在面向对象程序设计过程中 有时会面临要创建大量相同或相似对象实例的问题 创建那么多的对象将会耗费很多的系统资源 它是系统性能提高的一个瓶颈 例如 围棋和五子棋中的黑白棋子 图像中的坐标点或颜色 局域网中的路由器 交换机和集线器 教
  • Java设计模式-装饰者模式Decorator

    介绍 装饰者模式的核心思想是通过创建一个装饰对象 即装饰者 动态扩展目标对象的功能 并且不会改变目标对象的结构 提供了一种比继承更灵活的替代方案 需要注意的是 装饰对象要与目标对象实现相同的接口 或继承相同的抽象类 另外装饰对象需要持有目标
  • 分享几个项目中用到的设计模式

    前言 之前项目中出于扩展性和有雅性的考虑 使用了多种设计模式进行项目框架的设计 主要的一些设计模式是单例模式 工厂模式 策略模式 责任链模式 代理模式这几种 现在依次讲讲这几个的主要是实现方式和在我们项目中的应用场景 核心设计模式分享 单例
  • 每日一问:你想如何破坏单例模式?

    前言 1 单例是什么 单例模式 是一种创建型设计模式 目的是保证全局一个类只有一个实例对象 分为懒汉式和饿汉式 所谓懒汉式 类似于懒加载 需要的时候才会触发初始化实例对象 而饿汉式正好相反 项目启动 类加载的时候 就会创建初始化单例对象 1
  • 单例模式的八种写法比较

    单例模式是最常用到的设计模式之一 熟悉设计模式的朋友对单例模式都不会陌生 一般介绍单例模式的书籍都会提到 饿汉式 和 懒汉式 这两种实现方式 但是除了这两种方式 本文还会介绍其他几种实现单例的方式 让我们来一起看看吧 简介 单例模式是一种常
  • 设计模式之享元模式

    享元模式 就是共享技术 对于系统中存在大量相同的对象 把他们抽取成一个对象放在缓存中进行使用 这样可以大大节省系统资源 例如 围棋棋盘上有两种棋子 一个是黑子 一个是白子 如果在下棋的时候每下一个棋子就要new一个棋子对象 那么就会有大量的
  • [设计模式]模板方法模式(Template Method)

    1 意图 定义一个操作中的算法的骨架 而将一些步骤延迟到子类中 TemplateMethod使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤 2 动机 其实就是如意图所描述的 算法的骨架是一样的 就是有些特殊步骤不一样 就可以
  • Java设计模式之装饰者设计模式Decorator Pattern

    目录 一 基本概念 二 结构 1 图示 三 案例演示 被装饰对象的基类 一个接口 有cost 和description 两个抽象方法 具体被装饰的对象 实现上面这个接口 装饰者抽象类 基类 实现drink接口 具体的装饰者类 糖 具体装饰者
  • 程序员必知的23种设计模式之组合模式

    文章目录 1 模式引出 学校院系展示需求 1 1 传统方案 1 2 传统方案问题分析 2 组合模式基本介绍 2 1 方案修改 3 组合模式解决的问题 4 组合模式的注意事项和细节 1 模式引出 学校院系展示需求 编写程序展示一个学校院系结构
  • 设计模式-享元模式

    一 概念 如果在一个系统中存在多个相同的对象 那么只需要共享一份对象的拷贝 而不必为每一次使用都创建新的对象 目的是提高系统性能 上面的概念乍一听好像单例模式其实不是 单例模式只保存一个对象 但是这里可以有很多个不同对象 但是每个对象只有一
  • 设计模式(三)-结构型模式(4)-组合模式

    一 为何需要组合模式 Composite 在代码设计中 有种情况是对象之间存在层次关系 即对象之间会存在父结点和子结点的关系 比如在文件管理系统中 所有文件和文件夹形成树状结构 文件夹目录里存在子文件夹和文件 文件夹属于枝结点 文件属于叶结
  • 2023 年精选:每个 DevOps 团队都应该了解的 5 种微服务设计模式

    微服务彻底改变了应用程序开发世界 将大型整体系统分解为更小 更易于管理的组件 这种架构风格的特点是独立 松散耦合的服务 带来了从可扩展性 模块化到更高的灵活性等众多优势 DevOps 团队如何最好地利用这种方法来实现最高效率 答案在于理解并

随机推荐

  • springboot 整合logback,设置日志的输出路径

    一 logback配置相对路径 项目实战中 配置成这种模式 打成jar包执行 生成的logs目录和jar包在同一目录下 即平级状态 1 1 配置成logs 查看效果 1 2 配置成 logs 1 配置成 logs 2 生成结果 工程所在磁盘
  • Win10 wsl-安装教程

    一 安装原生Win10 1 网上随便找一个win10版本 制作成U盘启动 并完成安装 2 安装原生的win10 上述方案安装的win10不是原生的 存在各种问题 进入win10操作系统 下载最新的 MediaCreationTool 工具
  • webpack-----前端必会高频面试题

    webpack学习总结 面试题 1 什么是webpack 静态模块打包工具 2 webpack作用 分析 压缩 打包代码 3 webpack好处 减少文件体积 减少文件数量 提高网页加载速度 4 webpack工作流程 1 初始化参数 从配
  • 一个人再牛,最终还是要靠团队

    软件行业个人英雄主义时代已经渐渐远去 在CS以及自由软件盛行的年代 确实造就了许多的软件英雄 如今的互联网 时代 我们只能去怀念他们 无论是创业还是软件平台的研发与运营 我们都在强调着团队 马云再牛 没有十八罗汉 他也只不过是一个到处吹牛到
  • 报错解决TypeError: write() argument must be str, not list

    今天写爬虫的时候遇到的问题 将抓取的数据保存下来的时候报错 TypeError write argument must be str not list 字面意思是write写入的应该是str类型的数据 而不是一个list类型的数据 回到代码
  • x264的参考帧管理机制

    x264介绍 X264是一款研究的是H 264编码的开源代码软件 相比JM而言 其编码性能有很大的提高 其支持大多数H 264的特性工具 包括 CABAC和 CAVLC高效嫡编码 多参考帧预测 所有的帧内预测宏块类型 16x6l和4x4 所
  • 官宣——BSV工程师能力认证项目在CSDN推出线上学习平台

    去年11月 上海可一澈科技有限公司 以下简称 可一科技 与CSDN联合推出了BSV区块链开发工程师能力认证项目 以下简称 BSV工程师认证 今天 BSV工程师认证项目正式推出一个全新的线上学习平台 并发布首门课程 比特币协议与设计 本次推出
  • LDO基础知识:噪声 - 降噪引脚如何提高系统性能

    使用低压降稳压器 LDO 来过滤开关模式电源产生的纹波电压并不是实现清洁直流电源的唯一考虑因素 由于 LDO 是电子器件 因此它们会自行产生一定量的噪声 选择低噪声 LDO 并采取措施来降低内部噪声对于生成不会影响系统性能的清洁电源轨而言不
  • PYQT的最新界面代码

    This Python file uses the following encoding utf 8 import sqlite3 import traceback from PyQt5 QtGui import QMouseEvent Q
  • springboot入门简单使用

    springboot入门简单使用 1 SpringBoot项目创建并配置mysql数据库 创建项目 编写Controller测试 配置数据库 2 SpringBoot集成mybatis plus 初始化数据库 安装mybatis plus
  • 使用 imshow() 绘制矩阵

    使用 imshow 绘制矩阵 基础的展示效果 import matplotlib pyplot as plt import numpy as np mat np arange 0 100 reshape 10 10 plt imshow m
  • linux文件编程(4)—— 用ANSIC标准C库函数进行文件编程:fopen、fread、fwrite、fseek

    参考 linux文件编程 5 用ANSIC标准中的C库函数进行文件编程 作者 丶PURSUING 发布时间 2021 04 11 11 58 25 网址 https blog csdn net weixin 44742824 article
  • 深度优先搜索的框架

    深度优先搜索 最少分支找到答案 一 准备 1 节点间的relationship 2 列表lst 存放遍历结果 3 集合set 去重 二 结构 函数递归 def dfs root 1 首先判断根节点是否为空节点 if root is None
  • Python学习笔记-Python 变量类型

    变量是存储在内存中的值 这就意味着在创建变量时会在内存中开辟一个空间 变量赋值 Python 中的变量赋值不需要类型声明 每个变量在使用前都必须赋值 变量赋值以后该变量才会被创建 等号 用来给变量赋值 等号 运算符左边是一个变量名 等号 运
  • 【解决问题】mybatis-plus想要修改某字段为null问题

    背景 最近将框架的mybits换为mybits plus 然后在调用updateById时候 想让某个字段修改null 一直失败 问题 mybits plus调用updateById时候 想让某个字段修改null 一直失败 问题原因 myb
  • 2022最新个人所得税计算(附代码)

    相信大家一定很在意下面的三个问题 个人所得税怎么计算 年终奖如何扣税 五险一金如何计算 通过这篇文章 我们用实际例子来计算我们需要交的税 一 个人所得税怎么计算 第一步 计算全年收入 年终奖除外 做个假设 比如 博主上班后 开的工资是30k
  • React + antd +DatePicker组件禁用小于当下时间之前的时间,包括时,分

    一 DatePicker组件的设置 showTime设置时间只显示时 分 不显示秒 disabledDate函数 设置日期的禁用 disabledTime函数 设置时间的禁用
  • Centos 8 安装向日葵(sunloginclient-10.0.0-1)

    1 去官网下载最新的安装包 下载地址 2 准备安装 下面的问题可能遇到 但愿你们遇不到 如果没遇到问题 直接 rpm ivh sunloginclient 10 0 1 24347 amd64 rpm root yaco ls opt to
  • JavaScript中对象的简单使用实例(String、Math、Date、Array)

    String对象使用 JavaScript中的字符串对象 和字符串的常用方法 var s string 查看目标字符串是否可以匹配一个字符串 如果可以 则返回该字符串 否则返回空 alert s match str 返回字符出现的位置 al
  • 【设计模式】观察者模式

    观察者模式是一种行为型设计模式 它定义了一种一对多的依赖关系 当一个对象的状态发生改变时 其所有依赖者都会收到通知并自动更新 当对象间存在一对多关系时 则使用观察者模式 Observer Pattern 比如 当一个对象被修改时 则会自动通