前言
最近在遇到了 Android 的开发中常用到的设计模式之观察者模式,观察者模式,所谓的模式就是一种设计思想,可以按照某种模式,写出更合理,简单,有效的代码。可以用在 Android 开发中,也可以用在 Java,C#等等开发中,就类似单例模式,代理模式,模版等等。
观察者模式在实际项目中使用的也是非常频繁的,它最常用的地方是 GUI 系统、订阅——发布系统等。因为这个模式的一个重要作用就是解耦,使得它们之间的依赖性更小,甚至做到毫无依赖。以 GUI 系统来说,应用的 UI 具有易变性,尤其是前期随着业务的改变或者产品的需求修改,应用界面也经常性变化,但是业务逻辑基本变化不大,此时,GUI 系统需要一套机制来应对这种情况,使得 UI 层与具体的业务逻辑解耦,观察者模式此时就派上用场了。
一、观察者模式概念
1、定义
定义对象间的一种一对多的依赖关系,当一个对象的状态发送改变时,所以依赖于它的对象都得到通知并被自动更新。
2、介绍
- 观察者模式属于行为型模式。
- 观察者模式又被称作发布/订阅模式。
- 观察者模式主要用来解耦,将被观察者和观察者解耦,让他们之间没有没有依赖或者依赖关系很小。
3、使用场景
- 当一个对象的改变需要通知其它对象改变时,而且它不知道具体有多少个对象有待改变时。
- 当一个对象必须通知其它对象,而它又不能假定其它对象是谁
- 跨系统的消息交换场景,如消息队列、事件总线的处理机制。
4、举例说明
- 例一:生活中,我们一群人围着锅吃饭,饭好了,我们就开吃。(观察者:人们,被观察者:饭)
- 例二:Android 中,最常见的点击事件,通过设置控件的 OnClickListener 并传入一个 OnClickListener 的实现类来回调点击事件。(观察者:OnClickListener,被观察者:控件)
- 例三:Android 中,我们从 A 页面–>B 页面–>C 页面–>D 页面–>F 页面…. 我们想把 A 页面信息传递给最后一个页面,如果通过页面传递那么很繁琐,我们直接可以在需要的页面去订阅 A 页面的事件,当 A 页面刷行数据,其他订阅了 A 页面事件的就可以直接接受数据。(相当于少了中间商赚差价,是不爽了很多,而且效率还比较高)
- 例四:Android 中,我们常用的 recyclerView,listView 刷行数据时调用 notifyDataSetChanged()来更新 ui,想知道具体原因,那么请仔细往下看完这篇文章。
- 例五:Android 中,我们通常发送一个广播,凡是注册了该广播的都可以接收到该广播,这也是 Android 中典型的观察者模式。
二、观察者模式 UML 类图
角色介绍:
-
Subject(被观察者):把所有观察者对象的引用保存到一个集合里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,主要包含三个方法:
- addObserver 方法可以添加观察者对象,可以理解为观察者把自己注册到了被观察者这里,只有注册了的观察者,才能接到被观察者的通知。
- deleteObserver 方法是将观察者移除,被移除的观察者自然就不能再接到通知了。
- notifyObserves 方法可以把通知发送给所有的已注册的观察者,至于观察者们后续做什么事情,被观察者是完全不关心的。
-
Observer (抽象观察者):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
-
ConcreteSubject(被观察者的具体实现):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
- ConcrereObserver(观察者的具体实现):实现抽象观察者定义的更新接口,当得到主题更改通知时更新自身的状态。
三、观察者模式实现 Kotlin 实现
下面以日常生活中追剧案例实现观察者模式,如果电视剧更新,则会通知所有订阅者。(典型的一对多关系)
1、定义一个抽象主题,抽象被观察者
该抽象主题定义了一些通用的方法(订阅、取消订阅、通知),即具体主题里面需要实现的。
interface Observable {
/**
* 添加观察者
*/
fun addObserver(observer: Observer)
/**
* 移除观察者
*/
fun