23种设计模式之观察者模式

文章目录

23种设计模式之观察者模式

; 概述

观察者模式很好理解,类似于邮件订阅和RSS订阅,当我们浏览一些博客或wiki时,经常会看到RSS图标,就这的意思是,当你订阅了该文章,如果后续有更新,会及时通知你。其实,简单来讲就一句话:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系。

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

观察者模式的优缺点

  • *优点

(1)观察者模式可以实现表示层和数据逻辑层的分离,定义了稳定的消息传递机制,并抽象了更新接口,使得可以有各种各样的表示层充当具体的观察者角色。

(2)观察者模式在观察目标和观察者之间建立一个抽象的耦合。观察者对象只需要维持一个抽象观察者的集合,无需了解其具体观察者。

(3)观察者模式支持广播通信,观察目标会向所有已注册的观察者发送通知,降低了一对多系统的设计难度。

(4)观察者模式满足开闭原则的要求,增加新的具体观察者无须修改原有的系统代码。

  • *缺点

(1)如果一个观察目标对象有很多的直接观察者和间接观察者,那么所有的观察者接收到消息会耗费大量的时间。

(2)如果观察者和被观察者之间存在循环依赖,那么观察目标会触发它们之间进行循环调用,可能导致系统崩溃。

(3)观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道目标观察对象发生了变化。

观察者模式应用场景

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

观察者模式的结构和实现

模式结构

23种设计模式之观察者模式
  • Subject(目标或主题) 它是指被观察的对象。我们在主题中定义一个观察者集合。一个观察者对象可以接收任意多个观察者。同时提供了一系列的方法管理这些观察者。 比如attach添加观察者到集合中,detach从集合中剔除观察者。notify通知集合中的所有观察者。
  • ConcreteSubject(具体目标) 它拥有自己的状态,当它的状态的改变时就会通知各个观察者。 同时还实现了在目标类中定义的抽象逻辑方法(如果有的话)
  • Observer(抽象观察者) 它是一个接口,观察者将对观察目标状态的改变做出相应的反应 该接口定义了更新数据的方法update
  • ConcreteObserver(具体观察者) 具体观察者中会维护一个指向具体目标对象的引用,它存储了具体观察者的状态,这些状态和具体目标的状态要保持一致。 它实现了抽象观察者对象的updata方法。 通常在实现时,可以调用具体目标的attach和detach方法将自己加入到集合中或者从集合中剔除。

; 模式实现

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

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

23种设计模式之观察者模式
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();
      }
   }
}

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

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() ) );
   }
}

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() ) );
   }
}

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() );
   }
}

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);
   }
}

输出结果

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

总结

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

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

使用场景:

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

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

更多请移驾。。。

🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽

本文作者:Java技术债务
原文链接:https://www.cuizb.top/myblog/article/1659526753
版权声明: 本博客所有文章除特别声明外,均采用 CC BY 3.0 CN协议进行许可。转载请署名作者且注明文章出处。

🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽

23种设计模式之观察者模式
JVM内存泄漏和内存溢出的原因
JVM常用监控工具解释以及使用
Redis 常见面试题(一)
ClickHouse之MaterializeMySQL引擎(十)
三种实现分布式锁的实现与区别
线程池的理解以及使用
最近面试BAT,整理一份面试资料,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。想获取吗?如果你想提升自己,并且想和优秀的人一起进步,感兴趣的朋友,可以在扫码关注下方公众号。资料在公众号里静静的躺着呢。。。
23种设计模式之观察者模式
  • 喜欢就收藏
  • 认同就点赞
  • 支持就关注
  • 疑问就评论*
    一键四连,你的offer也四连**

Original: https://www.cnblogs.com/cuizb/p/16709536.html
Author: Java技术债务
Title: 23种设计模式之观察者模式

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/576234/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • MySQL常用数据类型及细节

    类型 类型举例 整数类型 TINYINT、SMALLINT、MEDIUMINT、INT(或INTEGER)、BIGINT 浮点类型 FLOAT、DOUBLE 定点数类型 DECIM…

    数据库 2023年5月24日
    084
  • English words1004

    本文来自博客园,作者:ukyo–BlackJesus,转载请注明原文链接:https://www.cnblogs.com/ukzq/p/16754120.html Or…

    数据库 2023年6月11日
    081
  • 汇编语言学习记录一

    0x00——什么是汇编语言? 汇编语言:早期实现程序员和机器进行交互的汇编指令集。 汇编指令,通过编译器,转换成机器码,从而使 机器 理解其指令。 0x01——汇编语言的组成 汇编…

    数据库 2023年6月11日
    083
  • docker部署mysql集群

    docker部署mysql集群 1.0 安装环境 1.1 安装Centos7 Docker官方建议在Ubuntu中安装,因为Docker是基于Ubuntu发布的,而且一般Docke…

    数据库 2023年6月9日
    094
  • Redis-切片集群

    扩容的思路 纵向扩展 scale up: 一台8G的变成一台24G的 👍 简单 👎 受硬件条件的限制 👎 单机容量大对性能的影响,如Redis的fork操作耗时是和内存数据量正相关…

    数据库 2023年6月11日
    072
  • fiddler的mock数据与二次开发示例

    fiddler的使用记录 fiddler了解 上官网下载工具,然后安装使用,https://www.telerik.com/fiddler,如果对该工具不熟悉,还有直白的教程,看过…

    数据库 2023年6月6日
    0116
  • Maven的工作机制

    Maven是 Apache 软件基金会组织维护的一款专门为 Java 项目提供 构建和 依赖管理支持的工具。 ·首先, Maven核心程序:负责Maven的总体调度,具体操作使用的…

    数据库 2023年6月16日
    082
  • Python–序列化与反序列化

    序列化是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态(存在内存中)写入到临时或持久性存储区(硬盘)。以后,可以通过从存储区中读取或反序列化对象的…

    数据库 2023年6月9日
    0106
  • apk生成多渠道的安装包

    一、前言->需求 最近公司的项目需要试上线,安卓包会放到多个渠道进行推广,玩家会进行下载安装登录,后台为了得到渠道包的下载使用数据,就会给每个渠道包加入了不同的渠道ID以便统…

    数据库 2023年6月14日
    0111
  • StoneDB 为何敢称业界唯一开源的 MySQL 原生 HTAP 数据库

    时代在召唤: HTAP Is On The Way 近些年,HTAP 正在受到人们越来越多的关注,Gartner 在 2014 年提出了 HTAP 这个术语和它的定义: Hybri…

    数据库 2023年5月24日
    083
  • 什么是ETCD及其应用场景

    源自公众号:BiggerBoy 一、什么是etcd? etcd 发音为/ˈɛtsiːdiː/,名字的由来,”distributed etc directory.&#82…

    数据库 2023年6月11日
    0118
  • day42-反射01

    Java反射01 1.反射(reflection)机制 1.1反射机制问题 一个需求引出反射 请看下面问题: 根据配置文件 re.properties 指定信息,创建Cat对象并调…

    数据库 2023年6月11日
    0126
  • Markdown学习

    Markdown学习 标题 三级标题 四级标题 字体 hello word hello word hello word hello word 引用 环境更加hi举报 分割线 图片 …

    数据库 2023年6月11日
    0103
  • Mysql客户端的安装

    Mysql数据库(简称)属于C/S架构,正常工作中一般都会提供服务端,我们只需要安装客户端进行查询修改数据等操作即可。 在正常工作中,无论是测试人员还是开发人员,总数据库管理员(测…

    数据库 2023年5月24日
    091
  • pg小工:pgsql的介绍

    支持邮件列表 http://www.postgresql.org/community/lists/ Original: https://www.cnblogs.com/lyhabc…

    数据库 2023年6月9日
    0102
  • 手把手教你使用 Java 在线生成 pdf 文档

    一、介绍 在实际的业务开发的时候,研发人员往往会碰到很多这样的一些场景,需要提供相关的电子凭证信息给用户,例如网银/支付宝/微信购物支付的电子发票、订单的库存打印单、各种电子签署合…

    数据库 2023年6月14日
    0113
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球