观察者模式
主题对象管理某些数据,观察者对象注册主题,当主题内的数据改变时,就会通知观察者对象,以便观察者对象在主题对象获取新数据时能够第一时间收到更新数据,注意的是观察者对象一定要注册对应的主题对象,如果不想继续获得数据了,则必须要取消注册,那么就不再监听主题对象的数据变化了
观察者模式定义了对象之间的一对多依赖,这 样一来,当一个对象改变状态时,它的所有依赖者都 会收到通知并自动更新
Demo
目的:WeatherData对象数据变化,会通知注册该对象的模版,然后对应的模版显示变化的数据
步骤
1.定义一个主题接口,其中包含注册、移除、通知观察者,所有的主题都需要实现这个接口
1 | public interface Subject { |
2.主题
1 | public class WeatherData implements Subject { |
3.定义一个观察者接口,所有观察者都必须实现这个类,实现update方法
1 | public interface Observer { |
4.定义一个显示的接口,所有观察者都必须实现这个类
1 | public interface DisplayElement { |
5.编写观察者
1 | //显示当前观测值 |
6.编写测试类
1 | public class Test { |
7.java也有内置的观察者接口(java.util
包内包含最基本的Observer
接口与Observable
类)
Observer
接口(观察者实现它)有一个void update(Observable o, Object arg);
方法
Observable
类(主题继承它)的方法,如下图
主题推送通知
其中setChanged()
方法,标记状态已经改变的事实,如果调用notifyObservers()
之前没有先调用setChanged()
,观察者就“不会”被通知
然后调用两种notifyObservers()
方法中的一个: notifyObservers()
或 notifyObservers(Object arg)
观察者接收通知
void update(Observable o, Object arg);
Observable o
主题本身当作第一个变量, 好让观察者知道是哪个主 题通知它的Object arg
这正是传入notifyObservers()的数据对象。 如果没有说明则为空
推和拉模式的区别与使用
推模型是假定主题对象知道观察者需要的数据;而拉模型是主题对象不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己去按需要取值。
推模型可能会使得观察者对象难以复用,因为观察者的update()方法是按需要定义的参数,可能无法兼顾没有考虑到的使用情况。这就意味着出现新情况的时候,就可能提供新的update()方法,或者是干脆重新实现观察者;而拉模型就不会造成这样的情况,因为拉模型下,update()方法的参数是主题对象本身,这基本上是主题对象能传递的最大数据集合了,基本上可以适应各种情况的需要。所以推荐使用拉模型