首页 > 其他分享 >观察者模式揭秘:实现松耦合的事件通知机制

观察者模式揭秘:实现松耦合的事件通知机制

时间:2023-12-24 12:33:22浏览次数:32  
标签:name 对象 通知 观察者 模式 揭秘 耦合 public

观察者模式揭秘:实现松耦合的事件通知机制_监听器

推荐语

本篇文章深度剖析了观察者模式的核心原理及其在软件开发中的重要应用,通过清晰而深入的讲解,读者小伙伴可以深入理解观察者模式如何实现松耦合的事件通知机制,从而构建更灵活、可扩展的软件系统。本文既适合希望深入了解设计模式的专业人士,也适合希望提升代码质量和可维护性的开发者。无论您是新手还是资深开发者,我相信都能从本文中有一些获益匪浅的!

什么是观察者模式

观察者模式是一种对象行为模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在观察者模式中,主题是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知。

观察者模式的核心原理

观察者模式是一种行为设计模式,其核心原理是对象之间的一对多依赖关系。在观察者模式中,当一个对象的状态发生改变时,它的所有依赖对象(也称为观察者)都会收到通知并自动更新。

观察者模式揭秘:实现松耦合的事件通知机制_监听器_02

观察者模式的核心角色:

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

观察者模式的核心原理可以概括为以下几点:

  1. 主题对象(被观察者)维护了一组观察者对象,并提供了方法来添加、移除和通知观察者。
  2. 观察者对象通过订阅主题对象,将自己注册为观察者。
  3. 当主题对象的状态发生改变时,它会遍历所有已注册的观察者,并调用它们的相应方法来通知和更新。
  4. 观察者对象根据接收到的通知,执行相应的操作,以便与主题对象保持一致的状态。

通过观察者模式,实现了主题和观察者之间的解耦,使得它们可以独立地变化。这样可以更灵活地设计和扩展系统,同时也提高了代码的可维护性和可重用性。

观察者模式如何实现

需求描述

明朝的锦衣服制度是一种特殊的政治制度,锦衣卫表面是上负责帮助皇帝管理仪仗,实际上是直属皇帝的特务机构,皇帝感觉哪个大臣有安全隐患,都会指挥锦衣卫派上一个眼线进行潜伏,暗中观察其一举一动,一旦有什么不好苗头,潜伏的眼线都会立马向上报告,锦衣卫马上出动进行逮捕、审讯。这一套流程下来,实际上就是观察者模式。如果写一个程序,怎么实现这个过程呢?

实现方法

观察者模式揭秘:实现松耦合的事件通知机制_设计模式_03

1、定义一个抽象的观察者,也就是锦衣卫,用来定义具体的职能,如逮捕、审讯等;

/** 
*锦衣卫 
*/
public interface JinYiWei {
    /**
     * 逮捕
     */
      void arrest(String something);
}

2、定义一个抽象主题,也就是眼线,用来执行添加观察者、删除观察者、通知观察者;

/** 
* 眼线
*/
public abstract class YanXian {
    public List<JinYiWei> jinYiWeiList = new ArrayList<JinYiWei>();

    /**
     * 添加
     *
     * @param jinYiWei
     */
    public void add(JinYiWei jinYiWei) {
        this.jinYiWeiList.add(jinYiWei);
    }

    /**
     * 移除
     *
     * @param jinYiWei
     */
    public void remove(JinYiWei jinYiWei) {
        this.jinYiWeiList.remove(jinYiWei);
    }

    public abstract void report(String something);
}

3、定义具体的主题,也就是皇帝的大臣,继承于抽象的主题,也就是眼线,大臣不管做什么事,都在被眼线的暗中观察着,并报告上级。

/** 
* 尚书大人 
*/
public class ShangShu extends YanXian {
    private String name;

    public ShangShu(String name) {
        this.name = name;
    }

    public void doSomething(String something) {
        System.out.println(this.name + something);
        //观察者开始工作
        this.report(this.name + something);
    }

    @Override
    public void report(String something) {
        for (JinYiWei jinYiWei : this.jinYiWeiList) {
            jinYiWei.arrest(something);
        }
    }
}

4、定义具体的观察者,也就锦衣卫的XX千户、XX 指挥使,用来执行具体的职能任务,如逮捕、审讯等;

/** 
* 锦衣卫千户大人 
*/
public class QianHu implements JinYiWei {

    private String name;

    public QianHu(String name) {
        this.name = name;
    }

    @Override
    public void arrest(String something) {
        System.out.println("报告皇帝:" + something);
        System.out.println(this.name + "准备执行逮捕任务");
    }
}

5、客户端

public class Client {  
    public static void main(String[] args) {        JinYiWei jinYiWei=new QianHu("锦衣卫的马千户");        ShangShu shangShu = new ShangShu("吏部的李尚书");
        shangShu.add(jinYiWei);
        shangShu.doSomething("写了一首反诗");
        ShangShu shangshu2=new ShangShu("兵部的王尚书");
        shangshu2.add(jinYiWei);
        shangshu2.doSomething("买了十副盔甲");
    }
}

观察者模式揭秘:实现松耦合的事件通知机制_设计模式_04

如何扩展

最近朱皇帝收到风声,将军们开始骄奢淫逸了,甚至开始强抢民女了,于派安插眼线,暗中搜集罪证,一旦证据确凿,马上逮捕,怎么实现这个过程呢?

观察者模式揭秘:实现松耦合的事件通知机制_监听器_05

定义具体的主题,也就是皇帝的将军,继承于抽象的主题,也就是眼线,将军们不管做什么事,都在被眼线的暗中观察着,并报告上级。

/** 
* 将军 
*/
public class JiangJun extends YanXian{    
    private String name; 
    public JiangJun(String name) {
        this.name = name;
    }
    public void doSomething(String something){
        System.out.println(this.name+something);
        this.report(this.name+something);
    }
    @Override
    public void report(String something) {
        for (JinYiWei jinYiWei : jinYiWeiList) {
            jinYiWei.arrest(something);
        }
    }
}
public class Client {   
    public static void main(String[] args) {       
        JinYiWei jinYiWei=new QianHu("锦衣卫的马千户");    
        ShangShu shangShu = new ShangShu("吏部的李尚书");   
        JiangJun jiangJun = new JiangJun("李将军");  
        jiangJun.add(jinYiWei);
        jiangJun.doSomething("纵容部下强抢民女");
    }
}

观察者模式揭秘:实现松耦合的事件通知机制_观察者模式_06

观察者模式适用哪些场景

业务场景具有下面的特征就可以使用观察者模式:

  1. 当一个抽象模型有两个方面,其中一个方面依赖于另一方面
  2. 当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变

有没有比较具体的业务场景示例呢?当然有,比如:

  1. 新闻评论功能:在此功能中,用户可以发布或删除留言,并自动追加留言和更新留言条数。为了实现这一功能,可以使用观察者模式。具体来说,留言模块、用户模块和提交模块可以作为被观察对象,而观察者模式可以用于在被观察对象发布消息时自动通知和更新观察者对象(例如,追加留言或更新留言条数)。
  2. 事件驱动的系统:观察者模式也适用于事件驱动的系统。在这种系统中,当一个事件发生时,需要通知所有注册过的观察者。观察者模式可以提供一种方便的方式来管理和通知所有的观察者。
  3. 数据变更通知:在某些业务场景中,当数据发生变更时,需要通知相关的用户或系统。观察者模式可以用于在这种数据变更发生时自动通知所有的观察者。
  4. 消息推送系统:在消息推送系统中,当有新的消息产生时,需要推送给相关的用户。观察者模式可以用于在这种消息发布时自动通知和更新观察者对象。
  5. 库存管理系统:在库存管理系统中,当库存量发生变化时,需要通知所有关注此变化的用户或系统。比如,当库存量低于某个阈值时,需要自动发送通知给负责补货的部门或人员。

观察者模式在Spring中的应用

  1. Spring MVC中的控制器(Controller):Spring MVC中的控制器类似于观察者模式中的观察者,它们监听并响应应用程序状态的变化。当应用程序状态发生变化时,控制器会接收到通知并执行相应的操作。
  2. Spring消息代理(Message Proxy):Spring消息代理可以用于实现异步消息通知。通过代理模式和观察者模式的结合使用,可以在应用程序中实现消息的自动分发和订阅。
  3. Spring AOP(面向切面编程):Spring AOP可以用于实现切面通知。通过使用观察者模式,可以在程序运行时自动执行切面逻辑,例如日志记录、事务管理等。
  4. Spring事件系统(Event System):Spring事件系统可以用于实现事件的发布和订阅。通过观察者模式,可以将事件和观察者关联起来,当事件发生时,所有订阅了该事件的观察者都会接收到通知。
  5. Spring消息队列(Message Queue):Spring消息队列可以用于实现消息的异步处理和消息的分布式发送。通过观察者模式,可以将消息队列和观察者关联起来,当有新消息到达时,所有订阅了该队列的观察者都会接收到通知。

关于观察者模式与监听器模式

从某种角度来说,观察者模式与监听器模式可以理解是一会事,但是从具体的实现细节上来说,还是有一些区别:

  • 观察者模式定义了一种一对多的依赖关系,使得当一个主题对象的状态发生变化时,所有依赖它的观察者都会得到通知并自动更新。在这种模式中,主题对象维护了一个观察者列表,并在其状态发生变化时通知所有的观察者。观察者对象不知道其他观察者的存在,它只知道如何更新自己。这种模式更适合于一对多的场景。
  • 监听器模式则是一种更适合一对一的通信场景的模式。在监听器模式中,监听器对象注册到时间源对象上,当时间源对象发生变化时,它会通知所有注册过的监听器。监听器对象知道其他监听器的存在,并且可以相互交互。在Springboot中,已经实现了具体的监听器机制,之前输出过两篇文章:

总结

优点

  1. 观察者模式在被观察者和观察者之间建立一个抽象的耦合,使得它们可以属于不同的抽象化层次。
  2. 观察者模式支持广播通信,即当被观察者的状态发生变化时,会通知所有的观察者。
  3. 观察者模式的实现方式符合“开闭原则”,即可以在不改变已存在的实现类的情况下,增加新的观察者类。

缺点

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

总之,观察者模式是一种非常有效的行为型设计模式,但是在使用观察者模式时需要谨慎考虑其优缺点,并确保在实践中能够有效地应用这种设计模式。

写在最后

当你读到这段话时,我相信我们是有缘相遇的。本文深入探讨了观察者模式的核心原理和在软件开发中的重要应用。通过本文的阅读,你将会了解到如何使用观察者模式实现松耦合的事件通知机制,从而打造更加灵活、可扩展的软件系统。无论你是想深入了解设计模式的专业人士,还是想提升代码质量和可维护性的开发者,本文都会对你有所启发和帮助。如果你喜欢本文,也请不要吝啬你的点赞和收藏,这不仅是对我们努力的肯定,更是给其他小伙伴推荐本文的信任和支持。感谢你的阅读,希望你能从中获得满意的收获!

标签:name,对象,通知,观察者,模式,揭秘,耦合,public
From: https://blog.51cto.com/fanfu1024/8955187

相关文章

  • 深入了解 Linux 网卡和网口:揭秘网络接口的奥秘
    实际工作中,把服务器关机了,网线从一个网口移动到了其他网口,导致再开机后,服务器无法联网了。由于缺少王工的支持,这使我开始关注网络技术。先总结下常用的概念和操作吧。1.网卡和网口的对应关系在Linux系统中,网卡(NetworkInterfaceCard,NIC)与网络接口(网口)之间存在紧密的对应关系。......
  • 观察者模式和发布订阅模式的区别
    观察者模式只有两个对象,一个是观察者(Listener)和被观察者;观察者通过实现被被观察者提供的接口,add到被观察者的Listener列表里;当被观察者内部产生相关事件时,通过其Listener列表来通知观察者; 而发布定义模式则多了一个中介(比如Kafka),即分为了生产者、中介、消费者三个角色了;生产......
  • 设计模式—观察者模式
    介绍代码观察者父类只有一个属性subject表示订阅的主题。update方法用于更新观察者本身publicabstractclassObserver{protectedSubjectsubject;publicabstractvoidupdate();}主题类主题类Subject直到自己的订阅者们,每当主题状态改变的时候就......
  • 组合模式揭秘:如何构建可扩展的树形结构
    什么是组合模式组合模式(CompositePattern)是一种结构型设计模式,它创建了对象组的树形结构,将对象组合成树状结构以表示“整体-部分”的关系。组合模式使得用户对单个对象和组合对象的访问具有一致性,即:组合能让客户以一致的方式处理个别对象以及组合对象。组合模式的核心原理组合模式......
  • 24届秋招薪资大揭秘!寒冬之下任吊打23届!!!
    最近秋招也接近尾声了,各家大厂也陆续开奖了。所以接下来我就结合牛客网和OfferShow的数据,给大家汇总一下,这届秋招各家公司的薪资情况。阅读声明:1、数据来源于牛客网和OfferShow,这些数据都是用户匿名自发上传的,所以不能保证数据100%正确。2、愿意分享数据的同学,通常......
  • 苹果推信imessage群发短信:海外拓客大揭秘
    想要拓展海外客户,却苦于没有合适的渠道?别担心,今天就给大家分享一个实用的方法——使用苹果imessage群发短信进行海外拓客。首先,你需要准备好你的苹果设备,并确保你的imessage已经启用。然后,你可以通过添加联系人或者使用现有的客户名单来创建你的短信群发对象。接下来,你可以编写一......
  • 软件多开助手大揭秘:一机多用,提升工作效率
    软件多开助手大揭秘:一机多用,提升工作效率在现代社会,计算机已经成为了我们工作和生活中不可或缺的工具。然而,许多人可能会遇到一个共同的问题:在同一台电脑上同时运行多个相同的软件程序。比如,一个人可能需要同时登录多个社交媒体账号,或者在不同的浏览器窗口中进行网页设计和开发工......
  • 观察者模式
    观察者模式通常由两个对象组成:观察者和被观察者。当被观察者状态发生改变时,它会通知所有的观察者对象,使他们能够及时做出响应,所以也被称作“发布-订阅模式”。示例代码/***@authorCreatedbynjyon2023/6/1*报纸接口,即被观察者接口*/publicinterfaceNewspaper{/*......
  • 观察者模式
    本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:1、理解观察者模式的动机,掌握该模式的结构;2、能够利用观察者模式解决实际问题。[实验任务一]:股票提醒当股票的价格上涨或下降5%时,会通知持有该股票的股民,当股民听到价格上涨的消息时会买股票,当价格下降时会大哭一场。1.......
  • Oracle内核技术揭秘 -- 存储结构
    区:表空间中的基本单位在Oracle11.2.0.3以上的版本中,创建新表默认不会分配区给这个表的,只有在插入了数据之后才会分配一个区给这个表空间。区是表空间中空间分配的基本单位,如果一个区的空间用完了,Oracle就会默认再分配一个区。Oracle专门设定了两种类型的表空间:统一大小表空间和......