首页 > 其他分享 >重修设计模式-行为型-观察者模式

重修设计模式-行为型-观察者模式

时间:2024-10-10 19:19:13浏览次数:11  
标签:observer Observer 重修 观察者 模式 fun EventBus 设计模式

重修设计模式-行为型-观察者模式

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

在对象之间订阅一个一对多的依赖,当一个对象状态改变时,它的所有依赖对象都会自动收到通知。

观察者模式(Observer Pattern)也被称为发布订阅模式(Publish-Subscribe Pattern),主要用于在对象之间建立一种一对多的依赖关系,当一个对象的状态发生变化时,能够自动通知所有依赖于它的对象,并让它们同步更新。观察者和被观察者之间一般通过抽象接口交互,耦合性低,扩展方便。

观察者(Observable)和被观察者(Observer)的称呼比价灵活,比如:Subject-Observer、Publisher-Subscriber、Producer-Consumer、Dispatcher-Listener 等,但只要符合上面的定义都可以看做是观察者模式。

观察者模式角色

  • 主题(Subject):被依赖的对象(1)。维护一个观察者列表,在状态发生变化时通知所有观察者。
  • 观察者(Observer):依赖的对象(N)。提供一个更新接口,在主题状态更新时会收到通知,处理相应逻辑。

观察者模式是一个比较抽象的模式,不同场景有不同实现,最经典的实现方式如下:

interface Subject<T> {
    fun register(observer: Observer<T>)
    fun remove(observer: Observer<T>)
    fun notify(msg: T)
}

interface Observer<T> {
    fun update(data: String)
}

class SubjectImpl: Subject<String> {
    private val mList = mutableListOf<Observer<String>>()

    override fun register(observer: Observer<String>) {
        mList.add(observer)
    }

    override fun remove(observer: Observer<String>) {
        mList.remove(observer)
    }

    override fun notify(msg: String) {
        mList.forEach { it.update(msg) }
    }
}

fun main() {
    val subject = SubjectImpl()
    subject.register(object: Observer<String> {
        override fun update(data: String) { println("observer 1 update:${data}") }
    })
    subject.register(object: Observer<String> {
        override fun update(data: String) { println("observer 2 update:${data}") }
    })
    subject.notify("消息变更数据...")
}

代码非常简单,算是观察者模式的“模板代码”,只能反映大体思路。观察者实现方式多种多样,在代码中遇到 register、attach、addObserver 等都可能是观察者模式的不同实现,不过万变不离其宗,设计思路是相似的。

观察者模式的应用场景

观察者模式应用非常广泛,比如发布-订阅系统,MQTT 协议是典型代表,股票价格监控,社交媒体的通知机制等。在移动开发中,有很多知名的三方库也应用了观察者模式,比如 EventBus、RxJava、ARouter、Lifecycle 等,它们都符合观察者模式的思想,只是实现方式会有不同,下面以 EventBus 为例,看它是如何实现的。

EventBus 是一种事件发布-订阅总线框架,旨在简化应用中组件间通信的复杂度。它的使用方式如下:

override fun onCreate(savedInstanceState: Bundle?) {
    //1.注册观察者
    EventBus.getDefault().register(this);
}

//2.定义观察方法,可指定执行线程
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent1(Event1 event) {
    //...
}

@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent2(Event2 event) {
    //...
}

override fun onStop() {
    //3.释放观察者
    EventBus.getDefault().unregister(this);
}

//other:
//4.状态更新事件,此时内部会通知onEvent1执行
EventBus.getDefault().post(new Event1());

EventBus 的使用非常简单,不过需要及时解注册,否则会有内存泄漏的风险。下面跟随使用方式,具体来看 EventBus 是如何实现的:

  1. register:注册观察者,接收任何类型,不同于经典实现,只接收一种类型的观察者。
  2. @Subscribe 注解:定义接收的消息(Event)类型,以及观察者的通知方法。
  3. unregister:移除观察者,会将其关联的 Event 方法移除。
  4. post:为观察者发送消息,只通知可匹配的观察者,也就是接收的消息类型(@Subscribe 方法)等于发送消息类型(post 的 Event 类型),或是其父类。

EventBus 核心维护了一个映射表,在 register 时遍历注册对象中 Subscribe 注解的方法,并将方法消息类型和对应方法存入映射表,在 post 时查询映射表,找到对应消息类型匹配的方法,并通过反射调用的方式进行通知,这就是 EventBus 的设计思想。

在 EventBus 内部,还维护了线程池,让 Subscribe 注解可以设置对应参数,来切换同步阻塞方式或异步非阻塞方式的场景。也就是说,观察者模式既可以同步阻塞方式实现,也可以异步非阻塞方式,甚至可以跨进程注册和通知,这些都是观察者模式在不同场景的不同实现。

类似观察者模式思想的还有个生产者 - 消费者”模型概念,它们的区别和联系如下:

  1. 它们设计目的都是为了解耦。
  2. 生产-消费用缓存队列进行解耦,生产和消费是无感知的;观察者模式需要存储被观察者对象,是有感知的。
  3. 生产-消费是天然异步非阻塞的,观察者模式可以选择不同实现方式。
  4. 生产-消费是多对多的,观察者模式是一对多的。

总结

观察者模式的应用场景非常广泛,小到代码层面的解耦,大到架构层面的系统解耦,再或者一些产品的设计思路,都有这种模式的影子。再复习一下它的定义:观察者模式能够在对象之间建立灵活的依赖关系,并在状态变化时实现自动通知和更新。

标签:observer,Observer,重修,观察者,模式,fun,EventBus,设计模式
From: https://blog.csdn.net/weixin_39397471/article/details/142830206

相关文章

  • C++常用设计模式详解
    前言:本文详细解释几种常用的C++设计模式,都是平时项目中用的比较多的。本文针对每种设计模式都给出了示例,让你跟着代码彻底搞懂设计模式。Tips:如果是准备面试,不需要知道所有的设计模式,要深入理解下面几种常用即可,因为面试官会先问你了解哪些设计模式,然后从你了解的里面挑一......
  • php设计模式(二)结构
    适配器模式(Adapter):结合两个不兼容的接口。GoF定义:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作<?phpclassmessage{publicfunctionsend(){echo'faxiaoix';}publicfunctio......
  • php设计模式(一)创建
    1、创建单例模式:确保一个类只有一个实例,并提供一个全局访问点。使用static静态变量和静态类工厂模式:主要是把工厂抽象出来一个抽象类,子类继承,通过子类构建,调用抽象工厂模式:抽象工厂模式的核心就是共创抽象类不止一个子类的构建,比如,我要发消息,还要推送一条消息,创建两个子类的......
  • 带你深入浅出设计模式:十二、桥接模式:连接抽象与实现的桥梁
    此为设计模式第十二谈!用总-分-总的结构和生活化的例子给你讲解设计模式!码农不易,各位学者学到东西请点赞收藏支持支持!开始部分:总:桥接模式的本质是将抽象部分与它的实现部分分离,使它们都能独立地变化。分:1.老规矩,自行打开VS创建一个控制台应用程序2.实现编码,这里以汽车......
  • 带你深入浅出设计模式:十一、组合实体模式:软件世界的乐高积木
    此为设计模式第十一谈!用总-分-总的结构和生活化的例子给你讲解设计模式!码农不易,各位学者学到东西请点赞收藏支持支持!开始部分:总:组合模式的目的:让客户端不再区分操作的是组合对象还是叶子对象,都以一个统一的方式来操作。分:1.老规矩,自行在vs创建一个控制台应用2.实现......
  • 设计模式——观察者模式
    哈喽,各位盆友们!我是你们亲爱的学徒小z,今天给大家分享的文章是设计模式的——观察者模式。定义定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。通用类图1.具体结构Subject被观察者定义被观察者必须实现的职......
  • 设计模式——门面模式 | 外观模式
    哈喽,各位盆友们!我是你们亲爱的学徒小z,今天给大家分享的文章是设计模式的——门面模式。文章目录定义通用类图1.通用结构2.优点3.缺点使用场景注意事项1.一个子系统可以有多个门面2.门面不参与子系统内的业务逻辑定义定义:要求一个子系统的外部与其内部的通信必须......
  • HourlyEmployee 和SalariedEmployee 设计模式实现
    1.1IntroductionNote:Thisassignmentisabitdifferentfromtheprevioushomework,andasksyoutopracticewithJUnit5.Ensureyoureadtheinstructionscarefullyandsubmitwhatisrequired.Volunteerworkisadmirable,butmanypeopleenjoybeingpaid......
  • Python 享元模式:高效利用内存的设计模式
    在Python编程中,随着程序规模的增大和数据量的增加,内存管理变得至关重要。享元模式(FlyweightPattern)作为一种结构型设计模式,为我们提供了一种在某些场景下有效管理内存、提高系统性能的方法。本文将深入探讨Python中的享元模式,包括其概念、关键要点、实现方式、应用场景......
  • Python 外观模式:简化复杂系统交互的设计模式
    在软件开发过程中,随着系统规模的不断扩大和功能的日益复杂,子系统之间的交互可能变得错综复杂。Python中的外观模式(FacadePattern)提供了一种有效的解决方案,它能够简化这些复杂的交互,为客户端提供一个统一、易用的接口来访问系统。本文将深入探讨Python中的外观模式,详细阐......