观察者设计模式

来源:互联网 发布:haoduofuli新域名 编辑:程序博客网 时间:2024/06/02 00:28

1. 概述

观察者模式定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。

Android 开发中一个比较典型的例子是点击监听器OnClickListener 。对设置 OnClickListener 来说, View 是被观察者, OnClickListener 是观察者,二者通过setOnClickListener() 方法达成订阅关系。订阅之后用户点击按钮的瞬间,Android Framework 就会将点击事件发送给已经注册的OnClickListener 。采取这样被动的观察方式,既省去了反复检索状态的资源消耗,也能够得到最高的反馈速度。当然,这也得益于我们可以随意定制自己程序中的观察者和被观察者

观察者模式可以看作是一种通知机制,可以实现一处通知,多处改变

2. Java API提供的观察者模式的实现

2.1 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;        synchronized (this) {            if (hasChanged()) {                clearChanged();                size = observers.size();                arrays = new Observer[size];                observers.toArray(arrays);            }        }        if (arrays != null) {            for (Observer observer : arrays) {                observer.update(this, data);            }        }    }    protected void setChanged() {        changed = true;    }}
  • 原理很简单,Observable中创建了一个List集合,用于存储观察者
  • addObserver添加观察者:往List集合中添加一个观察者对象
  • deleteObserver删除观察者:从List集合中删除一个观察者对象
  • notifyObservers更新数据:遍历List集合,调用观察者对象的update()方法,通知每一个观察者数据的更新

2.2 Observer观察者

public interface Observer {    /**     * This method is called if the specified {@code Observable} object's     * {@code notifyObservers} method is called (because the {@code Observable}     * object has been updated.     *     * @param observable     *            the {@link Observable} object.     * @param data     *            the data passed to {@link Observable#notifyObservers(Object)}.     */    void update(Observable observable, Object data);}

Observer接口只有一个方法,就是通知数据更新的方法update()

通常情况下,我们不会使用系统提供的观察者模式,因为使用java api提供的观察者模式,必须去继承Observable,而由于java单继承的局限性,所以我们一般情况下都是自己去实现观察者模式。其实系统提供的观察者模式很简单,我们自己去实现的时候,只需要模仿着java api写就可以了。

3. 观察者模式的实现

3.1 Observable

public class Teacher {     public String message;     //发布消息     public void publishMessage(String message) {         this.message = message;         notifyObservers(message);     }     List<MyObserver> observers = new LinkedList<>();     //添加观察者     public void addObserver(MyObserver observer) {         if (observer == null) {             throw new NullPointerException("observer is null");         } else             synchronized (this) {                 if (!observers.contains(observer)) {                     observers.add(observer);                 }             }     }     //删除观察者     public synchronized void deleteObserver(MyObserver observer) {         observers.remove(observer);     }     //通知观察者数据改变     public void notifyObservers(String message) {         for (MyObserver observer : observers) {             observer.update(message);         }     } }

3.2 Observer

public interface MyObserver {         void update(String message);     }
public class Student implements Teacher.MyObserver {      @Override      public void update(String message) {          System.out.println(getClass().getSimpleName()+"收到"+message);      }  }

3.3 观察者模式的使用

public class Test {    public static void main(String[] args){        Teacher teacher = new Teacher();        Student student = new Student();        teacher.addObserver(student);        teacher.publishMessage("同学们,今天没有作业");        }    }

4. ListView中的观察者模式

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();    }    public void notifyDataSetInvalidated() {        mDataSetObservable.notifyInvalidated();    }}

DataSetObservable

public class DataSetObservable extends Observable<DataSetObserver> {    public void notifyChanged() {        synchronized(mObservers) {            for (int i = mObservers.size() - 1; i >= 0; i--) {                mObservers.get(i).onChanged();            }        }    }    public void notifyInvalidated() {        synchronized (mObservers) {            for (int i = mObservers.size() - 1; i >= 0; i--) {                mObservers.get(i).onInvalidated();            }        }    }}

DataSetObserver

public abstract class DataSetObserver {    public void onChanged() {    }    public void onInvalidated() {    }}

AdapterView

public abstract class AdapterView<T extends Adapter> extends ViewGroup {    class AdapterDataSetObserver extends DataSetObserver {    }}

AbsListView

public abstract class AbsListView extends AdapterView<ListAdapter>{    class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {    }}

5. 观察者模式的应用

  • RxJava
  • Data Binding
  • EventBus
  • Broadcast
  • Loader
  • ListView
  • GridView
  • RecyclerView
  • Loader
0 0