很早之前就想写这个东西了,那时候刚学习软件开发,接触到了接口,然后是回调函数,然后是思考安卓的按钮监听事件。
定义
观察者模式又称为发布订阅模式。它的现实场景是早上有课,闹钟响了,寝室里的同学都醒过来准备去上课了。那么我们在现实世界的很多需求都是可以抽象成这个模式的。业务逻辑能很清楚的划分出观察者(订阅者订阅)和被观察者(发布者发布)对于我们梳理需求和后面的工程维护都是很有帮助的,而且这个模式效率也是很高的,我想象了一下,如果不采取这个模式我早上怎么知道要去上课了呢?除了轮询我想不到还有什么方法(或者我设置一个代理),那我得过一会儿就要看一下时间,要保证尽可能不迟到那我这个轮询时间还必须得短一些,增加看时间的频次,那就很辛苦了。或者如果是时间感很好的同学可能看一下时间等到了该起床的时间就自然能起也是了不起。
实现
实现观察者模式有很多形式,比较直观的一种是使用一种“注册——通知——撤销注册”的形式。下面的图片详细的描述了这样一种过程:
观察者
(Observer)将自己注册(register/attach)到被观察对象(Subject)中,因为可以有多个观察者,一般Subject的register、attach方法里面都会是一个数组、列表等数据结构。被观察对象将观察者实例存放在这个容器(Container)里。
被观察者
被观察对象发生了某种变化(如图中的SomeChange),从容器中得到所有注册过的观察者,将变化通知观察者。撤销观察
观察者告诉被观察者要撤销观察(remove/detach),被观察者从容器中将观察者去除。
之前的实现源码
myCallBack.java
public abstract interface myCallBack{
void changePlayingSongName(String songName);
void changePlayOrPauseIcon();
}
MusicService.java
public void playSelectedSong(int songId) {
...
for (int i = 0; i < list.size(); i++) {
list.get(i).changePlayingSongName(localSong.getTitle());
list.get(i).changePlayOrPauseIcon();
}
}
public static ArrayList<myCallBack> list = new ArrayList<myCallBack>();
PlayMusicActivity.java
MusicService.list.add(callback);
@Override
public void changePlayingSongName(String songName) {
tv_songname.setText(songName);
}
@Override
public void changePlayOrPauseIcon() {
iv_start.setImageResource(R.drawable.lockscreen_pause);
}
跋
因为每个人能定多个闹钟,对于闹钟这个被观察者/notifier它可以有多个时间点/多个事件,他会按照顺序发送事件、唤醒观察者observer按顺序接收和执行观察者事件