设计模式--观察者模式

来源:互联网 发布:背四级英语单词的软件 编辑:程序博客网 时间:2024/05/21 22:36

定义?
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。

观察者模式的作用是什么?
观察者模式的主要作用就是对象解耦,将观察者和被观察者完全隔离,只依赖于Observer和Observable抽象。

观察者模式的简单实现
很多技术网站支持用户邮箱订阅,每周发布周报后会将优质的内容推送给订阅用户。

    /**     * 程序员是观察者     */    public class Coder implements Observer {        public String name;        public Coder(String name) {            this.name = name;        }        @Override        public void update(Observable observable, Object data) {            System.out.print(name + data);        }        @Override        public String toString() {            return name;        }    }
    /**     * 技术网站是被观察者,当它有更新时所有的观察者(程序员)都会接收到相应的通知     */    public class DevTechFrontier extends Observable {        public void postNewPublication(String content) {            //标示状态,内容发生改变            setChanged();            //通知所有的观察者            notifyObservers();        }    }
    /**     * 测试代码     */    public class Test {        public  void main(String[] args) {            //被观察者            DevTechFrontier devTechFrontier=new DevTechFrontier();            //观察者            Coder coder1=new Coder("coder-1");            Coder coder2=new Coder("coder-2");            Coder coder3=new Coder("coder-3");            //将观察者注册到列表中            devTechFrontier.addObserver(coder1);            devTechFrontier.addObserver(coder2);            devTechFrontier.addObserver(coder3);            //发布消息            devTechFrontier.postNewPublication("新的一期技术周报发布了!");        }    }

输出结果:
coder-1,新的一期技术周报发布了!
coder-2,新的一期技术周报发布了!
coder-3,新的一期技术周报发布了!

可以看到,所有订阅的用户都收到了更新消息,一对多的订阅。
这里Observer是抽象的观察者,Coder是具体的观察者;Observable是抽象被观察者,DevTechFrontier 是具体的可观察对象。Coder是观察者,它们订阅了DevTechFrontier 这个具体的可观察对象,当DevTechFrontier 有更新时,会遍历所有的观察者Coder,然后给这些观察者发布一个更新消息,即调用Coder的update方法,这样就达到了一对多的通知功能。在这个通知过程中,通知系统都是依赖Observer和Observable这两个抽象类,因此,对于Coder和DevTechFrontier 完全没有耦合。

JDK中的Observer接口和Observable类实现
1.在Observer接口源代码中只声明一个update()方法

public interface Observer {    void update(Observable var1, Object var2);}

被观察者的对象当改变时调用这个方法。实现这个接口的类,可以作为观察者。

2.Observable类,被观察者,消息的发出者,继承此类可以扩展。

public class Observable {    //观察者的集合    List<Observer> observers = new ArrayList<Observer>();    boolean changed = false;    public Observable() {    }    public void addObserver(Observer observer) {        if (observer == null) {            throw new NullPointerException("observer == null");        }        synchronized (this) {            if (!observers.contains(observer))                observers.add(observer);        }    }    protected void clearChanged() {        changed = false;    }    public int countObservers() {        return observers.size();    }    public synchronized void deleteObserver(Observer observer) {        observers.remove(observer);    }    public synchronized void deleteObservers() {        observers.clear();    }    public boolean hasChanged() {        return changed;    }    public void notifyObservers() {        notifyObservers(null);    }    //通知所有订阅此主题的观察者对象      @SuppressWarnings("unchecked")    public void notifyObservers(Object data) {        int size = 0;        Observer[] arrays = null;        //这里为啥要同步?        //保证observers集合的数据唯一        synchronized (this) {            if (hasChanged()) {                clearChanged();                size = observers.size();                arrays = new Observer[size];                observers.toArray(arrays);            }        }        //这里为什么没有同步?        //观察者的updata操作可能是耗时操作        if (arrays != null) {            for (Observer observer : arrays) {                observer.update(this, data);            }        }    }    protected void setChanged() {        changed = true;    }} 

Android源码分析
ListView是Android中最重要的控件之一,而ListView最重要的一个功能是Adapter。通常,我们往ListView添加数据后,都会调用Adapter的notifyDataSetChange。下面对这个方法的源码进行分析。
notifyDataSetChange这个方法定义在BaseAdapter中,具体代码如下:

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {    //数据集观察者    private final DataSetObservable mDataSetObservable = new DataSetObservable();    public void registerDataSetObserver(DataSetObserver observer) {        mDataSetObservable.registerObserver(observer);    }    public void unregisterDataSetObserver(DataSetObserver observer) {        mDataSetObservable.unregisterObserver(observer);    }    /**    *当数据集发现变化时,通知所有观察者     */    public void notifyDataSetChanged() {        mDataSetObservable.notifyChanged();    }}

接下来看mDataSetObservable.notifyChanged()的源码:

/***数据集观察者*/public class DataSetObservable extends Observable<DataSetObserver> {    //调用每个观察者的onChanged方法来通知它们被观察者发生了变化    public void notifyChanged() {        synchronized(mObservers) {            for (int i = mObservers.size() - 1; i >= 0; i--) {                mObservers.get(i).onChanged();            }        }    }}

这部分代码很简单,就是在mDataSetObservable.notifyChanged()中遍历所有的观察者,并且调用它们的onChanged方法,从而告知观察者发生了变化。

1 0