设计模式:观察者模式

这是张富涛的第3篇原创

设计模式:观察者模式

1. 简介

观察者模式:有时也被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

如果简单的介绍观察者模式,那就像拍卖的时候,“拍卖师”观察最高标价,然后通知给其他竞价者竞价。我们将“拍卖师”看做一个观察者,将最高标价看做一个主题事件,当最高标价发生了改变的时候,我们就要通知所有的“竞价者”:最高标价发生了变化,这就是观察者模式。

2. 简单实现

假设你现在在做一个网上商城的项目,你需要写一个接口监听订单(Order)的订单状态(status),只要这个订单的状态发生了变化,就要程序执行一定的业务逻辑,而这个业务逻辑我们并不知道。

本着面向对象设计的开闭原则,我们采用了观察者模式,我们的设计中,打算创建一个或多个监听器监听这个订单的状态,当订单状态发生改变时,我们就通知所有的监听者,告诉他们这个状态发生了改变,你们可以执行自己的业务逻辑了。

这个代码的设计类图是这样的:

根据面向对象原则,我们设计了一个EventListener(事件监听器)接口,写了一个如果订单变化时会执行的方法。同时我们设计了一个Order(订单)类,里面只有两个基本属性:id(订单id)和status(订单状态),我们要将监听一个订单的状态变化,可能会执行多个业务逻辑,所以可能会注册多个监听器,所以我们又设计了一个数组listeners。

(代码中使用的Vector类是jdk提供的可以实现自动增长的对象数组,因为我们不确定使用者将注册几个监听器,无法初始化的时候规定它的长度)

那么接下来我们看一看代码的简单实现吧:

首先我们创建了一个名为“EventListener”的接口,并在里面一个如果订单变化时会执行的方法。

然后我们创建了订单类,设置了三个私有属性id、status和listeners。此处为了示例,将状态设置只有两种:成功和未成功,默认是未成功。同时在构造函数中初始化listeners。

既然我们将listeners设置成了私有,那我们就写几个公有的可以操作他的值的方法吧。

接下来我们继续完善Order类,现在我们未完成的工作有:为id、status增加get/set方法,实现订单改变之后通知所有的监听器。

我们在setStatus方法里增加了一个简单的判断,如果status属性进行了更改,就遍历listener中所有的监听器,并且执行他们的onOrderStatusChange()方法。

至此,我们的观察者模式已经写完了,接下来让我们测试一下吧。

我们使用匿名内部类的方式声明了3个监听器,比如他们里面执行了不同的代码逻辑。

最终的执行结果为:

至此,我们实现了观察者的一对多的依赖关系,让多个观察者对象(EventListener)同时监听了Order类的status属性变化。其实这个代码还有一个小bug,bug发生在这段代码中。

我们需要在其中增加这样一段话:

看到这里,你不禁会疑惑,为什么需要克隆一个数组呢? 原因是listeners是Order的属性,在我们执行notifyListener()的同时,这个数组中的监听器可能会被执行增加,也可能会执行删除,甚至是全部清除,这样就可能造成多通知或者少通知的bug。于是我们克隆一个数组出来进行遍历。

3. JDK提供的监听器模式

在我们学会了自己写一个观察者模式之后,JDK也为我们提供了一套方便的观察者模式写法。在这套写法中,我们不需要写EventListener这种监听器,实现起来的代码其实很简单:

我们将Order类继承JDK提供的Observable类,此时不需要我们自己写监听器的数组了,在status属性更改的时候调用setChanged()方法通知父类要监听的属性发生了改变和notifyObservers()方法通知所有监听器即可。

因为监听器实际上JDK已经封装好了,我们创建好order对象之后只需要调用addObserver方法,在其中以匿名内部类的方式new一个Observer类,并且重写其update()方法,看到这里你是不是觉得有些熟悉? 没错,这跟我们之前写的代码如出一辙,我们将之前的执行逻辑写进去。

最终的结果是:

以上就是观察者模式了,到了这里相信你已经了解观察者模式的原理和简单的实现方法,那么心动不如行动,赶快将这些知识转化为自己的知识,动手去实践一下吧!



---------------

公众号:张富涛的学习笔记(ID:futaoNT)

知乎:张富涛

CSDN:张富涛

B站:你给的宝物

这是一个在夜晚可以靠编程拯救世界的程序员,关注他将在第一时间获悉他的知识、工作心得!

长按下图二维码关注:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值