写爽了,再来一篇观察者。
看,右面有个小萝莉!!!哪呢哪呢我瞅瞅??
哇,左面有个大御姐!!!哪呢哪呢我瞧瞧??
我就是观察者,观(tou)察(kui)就完事儿了~~哈哈哈哈哈哈哈
书归正题啊,观察者模式算是我用的比较多的一种模式了(RxJava赛高!)。首先,学习观察者模式我们需要两个类。Observer和Observable。顾名思义,一个观察者一个被观察者。让我们幻想一下场景,平时无聊的时候刷朋友圈,肯定是看个个小美女的动态啊23333。这时候就是一种观察的状态了。那我们就开始写代码吧!!
一个被观察者小萝莉,继承了Observable,实现了WonderfunlGirl接口中的sendMoments方法。方法中调用了Observable中的俩个方法。注意一下,notifyObservers方法中自己已经调用了clearChanged,所以不用手动调用再一次改变状态了。
public class Lolita extends Observable implements WonderfulGirl {
public void sendMoments() {
setChanged();//改变状态
notifyObservers("今天和funky哥一起去玩,真开心啊~~");//通知所有的观察者,比如我
}
}
有了观察者,那大色狼。。。不,观察者funky我也得有啊。发了朋友圈没人看,美女也不开心是吧。
public class Funky implements Observer {
private static final String TAG = Funky.class.getSimpleName();
@Override
public void update(Observable observable, Object arg) {
Log.i(TAG, "噢噢噢噢!!小萝莉发朋友圈写到:" + arg.toString());
}
}
那我们的主函数应该怎么写呢???
Lolita lolita = new Lolita();
Funky funky = new Funky();
lolita.addObserver(funky);
lolita.sendMoments();
输出结果显而易见:
那这种订阅模式到底是怎么实现的呢??我们先看看被观察者的源码。
public class Observable {
//记录改变状态
private boolean changed = false;
//一个观察者的集合,小细节,因为要经常遍历所以用ArrayList
private final ArrayList<Observer> observers;
public Observable() {
observers = new ArrayList<>();
}
//添加观察者
public synchronized void addObserver(Observer observer) {
if (observer == null)
throw new NullPointerException();
if (!observers.contains(observer)) {
observers.add(observer);//在集合中添加观察者
}
}
//删除观察者
public synchronized void deleteObserver(Observer observer) {
observers.remove(observer);//在集合中删除观察者
}
//通知观察者
public void notifyObservers() {
notifyObservers(null);//发送空信息
}
//通知观察者,并发送信息
public void notifyObservers(Object arg) {
Observer[] arrLocal;//临时数组
synchronized (this) {//锁=。=
if (!hasChanged())//现在还改变么?
return;
//把当前的观察者集合Arraylist变成数组
arrLocal = observers.toArray(new Observer[observers.size()]);
//行了,现在就改变状态吧,因为上面代码需要通知的观察者们已经被存起来了
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)//遍历临时数组
//调用observer的updata,真正的把数据通知给每个观察者
arrLocal[i].update(this, arg);
}
//删除所有关注自己的人
public synchronized void deleteObservers() {
observers.clear();
}
//设置状态为正在改变
protected synchronized void setChanged() {
changed = true;
}
//设置状态为不改变
protected synchronized void clearChanged() {
changed = false;
}
//现在的状态码是啥
public synchronized boolean hasChanged() {
return changed;
}
//关注人数,看自己是不是大V
public synchronized int countObservers() {
return observers.size();
}
}
被观察者Observable的源码特别简单,其实就是
简单的内部数据集合的增删改查。值得注意的是几乎所有的方法都有synchronized来修饰,只有notifyObservers这个方法不是synchronized修饰。他内部有一部分同步的代码块用来存储需要通知的所有观察者。这样的写法连作者都用了一个 (should not)当做注解2333。这样就会出现两种问题。
1.新增的观察者将错过正在进行的通知
2.最近已经关取的观察者会被错误地通知。
算是两个比较好玩的细节吧。
接下来让我们看看观察者的源码:
public interface Observer {
/**
* 就一个更新数据的方法,好嘛
*/
void update(Observable o, Object arg);
}
好着来~更简单,Observer就是个接口,只要实现其中的更新方法就行了。
6点了下班,下节课让我们看看Android开发中必用的BaseAdapter如何使用观察者模式与观察者模式的大成者RxJava的使用方法啦啦啦啦,下课