[置顶] Design Pattern 之 观察者模式

转载请注明出处:http://blog.csdn.net/crazy1235/article/details/51815880

观察者模式介绍

观察者模式 又称为 发布-订阅模式 。定义了一种一对多的依赖关系,当被观察者对象状态发生改变时,通知所有依赖于它(订阅它)的观察者对象。

RSS订阅 和 邮件订阅 大家应该都知道,你订阅后,将会及时获得所订阅的相关最新内容。所有订阅该内容的“订阅者”,当该内容有更新时,就可以收到通知。这就是一种观察者模式的应用场景。

UML图

java中,内置了ObserverObservable,分别表示抽象的观察者对象和抽象主题角色(可被观察,被观察者)。

[置顶] Design Pattern 之 观察者模式_第1张图片

Observer是一个借口,定义了一个update方法。

public interface Observer {
    void update(Observable o, Object arg);
}

观察者模式应用

先来看看JDK中Observer和Observable的源码。

Observer

public interface Observer {
    /** * 更新操作 */
    void update(Observable o, Object arg);
}

该类是一个 接口 ,只有一个更新的函数。

Observable


package java.util;

/** * 表示一个可被观察的对象 * 一个被观察者可以有多个观察者对象 * 调用 notifyObservers 方法可以通知所有的观察者调用他们的 update 方法 * 当一个被观察者被初始创建的时候,它的观察者set集合是空的 */
public class Observable {
    private boolean changed = false;
    private Vector<Observer> obs; // 通过向量保存观察者对象

    /** Construct an Observable with zero Observers. */

    public Observable() {
        obs = new Vector<>();
    }

    /** * 添加一个观察者对象 * * @param o an observer to be added. * @throws NullPointerException if the parameter o is null. */
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

    /** * 删除一个观察者对象 * * @param o the observer to be deleted. */
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }

    /** * 当对象发生变化是,首先调用hasChanged表明发生了改变,然后通知所有的观察者对象,调用它们各自的update方法,最后调用clearChanged方法表明当前对象已经没有改变了。 * 每个观察者对象都有它的update方法,该方法有两个参数 * * @see java.util.Observable#clearChanged() * @see java.util.Observable#hasChanged() * @see java.util.Observer#update(java.util.Observable, java.lang.Object) */
    public void notifyObservers() {
        notifyObservers(null);
    }

    /** * arg参数最终会赋值给update函数的第二个参数 * * @param arg any object. * @see java.util.Observable#clearChanged() * @see java.util.Observable#hasChanged() * @see java.util.Observer#update(java.util.Observable, java.lang.Object) */
    public void notifyObservers(Object arg) {

        Object[] arrLocal;

        synchronized (this) {
            //由此可以看书,如果没有changed == false,直接return,后序代码不执行。
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        //倒序遍历观察者对象数组,调用update方法。由此看出,后添加进来的观察者对象会被先调用update方法。
        for (int i = arrLocal.length-1; i>=0; i--) 
            ((Observer)arrLocal[i]).update(this, arg);
    }

    /** * 清楚所有的观察者对象 */
    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }

    /** * 设置改变标志,只有调用了该方法,观察者对象才能被通知。 */
    protected synchronized void setChanged() {
        changed = true;
    }

    /** * 重置改变标志 * * @see java.util.Observable#notifyObservers() * @see java.util.Observable#notifyObservers(java.lang.Object) */
    protected synchronized void clearChanged() {
        changed = false;
    }

    /** * 判断是否有改变 * * @see java.util.Observable#clearChanged() * @see java.util.Observable#setChanged() */
    public synchronized boolean hasChanged() {
        return changed;
    }

    /** * 返回观察者对象的数量 */
    public synchronized int countObservers() {
        return obs.size();
    }
}

基本应用

/** * 被观察者类 继承Observable类,表示这个类可以被观察。 * * @author Admin * */
public class SimpleObservable extends Observable {
    private int data = 0;

    public int getData() {
        return data;
    }

    public void setData(int data) {
        if (this.data != data) {
            this.data = data;
            // 标志状态改变,一定要调用函数notify方法才有效
            setChanged();
            // 通知所有观察者
            notifyObservers("abc");
        }
    }

}
/** * 观察者1号 * * @author Admin * */
public class SimpleObserver implements Observer {

    public SimpleObserver(SimpleObservable simpleObservable) {
        simpleObservable.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("SimpleObserver: " + ((SimpleObservable) o).getData() + " -- " + (String)arg);
    }
}
/** * 观察者2号 * @author Admin * */
public class OtherObserver implements Observer{

    public OtherObserver(SimpleObservable observable){
        observable.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("OtherObserver: " + ((SimpleObservable)o).getData() + " -- " + (String)arg);
    }
}
public class SimpleTest {
    public static void main(String[] args) {
        SimpleObservable observable = new SimpleObservable();

        new OtherObserver(observable);
        new SimpleObserver(observable);

        observable.setData(1);
        observable.setData(2);
        observable.setData(2);
        observable.setData(4);
    }
}

测试的结果如下:

SimpleObserver: 1 -- abc
OtherObserver: 1 -- abc
SimpleObserver: 2 -- abc
OtherObserver: 2 -- abc
SimpleObserver: 4 -- abc
OtherObserver: 4 -- abc

异步观察者模式

上面介绍的都是同步观察者模式。同步观察者模式会有阻塞问题。各个观察者按照顺序执行update方法。一旦有一个observer比较耗时的话,后序的observer也得等着。

异步观察者模式就不一样,不会有这样的阻塞问题。

针对update方法做文章

/** * 异步观察模式的观察者接口 */
public interface AsyncObserver {

    /** * * @param o * @param arg */
    void update(AsyncObservable o, Object arg);

}
/** * 异步观察者模式的被观察者对象 */
public class AsyncObservable {

    private boolean changed = false;
    private Vector<Wrapper> obs;

    public AsyncObservable() {
        obs = new Vector<>();
    }

    /** * * @param wrapper */
    public synchronized void addObserver(AsyncObserver o) {
        if (o == null)
            throw new NullPointerException();
        Wrapper wrapper = new Wrapper(o);
        if (!obs.contains(wrapper)) {
            obs.addElement(wrapper);
        }
    }

    /** * */
    public synchronized void deleteObserver(AsyncObserver o) {
        Iterator<Wrapper> iterator = obs.iterator();
        while (iterator.hasNext()) {
            Wrapper wrapper = iterator.next();
            if (wrapper.getAsyncObserver() == o) {
                obs.remove(wrapper);
                break;
            }
        }
    }

    /** * */
    public void notifyObservers() {
        notifyObservers(null);
    }

    /** * */
    public void notifyObservers(Object arg) {

        Object[] arrLocal;

        synchronized (this) {

            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length - 1; i >= 0; i--)
            ((Wrapper) arrLocal[i]).update(this, arg);
    }

    /** * */
    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }

    /** * */
    protected synchronized void setChanged() {
        changed = true;
    }

    /** * */
    protected synchronized void clearChanged() {
        changed = false;
    }

    /** * */
    public synchronized boolean hasChanged() {
        return changed;
    }

    /** * */
    public synchronized int countObservers() {
        return obs.size();
    }

}
/** * 观察者的包装类 */
public class Wrapper {

    private AsyncObserver observer;

    public Wrapper(AsyncObserver o) {
        this.observer = o;
    }

    public AsyncObserver getAsyncObserver() {
        return observer;
    }

    /** * * @param observable * @param o */
    public void update(AsyncObservable observable, Object o) {
        new Handler(observable, o).start();
    }

    class Handler extends Thread {

        AsyncObservable observable;
        Object object;

        public Handler(AsyncObservable observable, Object o) {
            this.observable = observable;
            this.object = o;
        }

        @Override
        public void run() {
            observer.update(observable, object);
        }
    }
}

最主要的就是这个Wrapper包装类。被观察者的notify方法内部实际上调用的是Wrapper类中的update()方法。

将每个update操作放到一个线程中去。这样多个线程“同时”工作。

这样即是某些观察者类的update做一些耗时操作,也不影响其他观察者类的update的工作、


测试结果:

hahahaha
hahahaha
hahahaha
hahahaha
hahahaha
hahahaha
hahahaha
hahahaha
hahahaha
ObserverB -- i think jingjing -- jingjing
hahahaha
ObserverC -- i think jingjing -- jingjing
ObserverA -- i think jingjing -- jingjing

总结

观察者模式中,被观察者与观察者通过接口进行联系。被观察者只知道一个观察者列表,列表中的每个对象都是一个抽象观察者接口。

Android中观察者模式的应用场景有:

  • 广播机制

  • ListView数据更改

  • 点击事件

  • ContentObserver

完毕。

:-D

晚安~

你可能感兴趣的:(设计模式,观察者模式,Pattern,发布订阅)