Re:Android 设计模式-观察者

写爽了,再来一篇观察者。

看,右面有个小萝莉!!!哪呢哪呢我瞅瞅??

哇,左面有个大御姐!!!哪呢哪呢我瞧瞧??

我就是观察者,观(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的使用方法啦啦啦啦,下课

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值