Skip to content

Latest commit

 

History

History
304 lines (248 loc) · 8.83 KB

观察者设计模式.md

File metadata and controls

304 lines (248 loc) · 8.83 KB

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 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 {
    }
}

在ListView的setAdapter()中添加观察者

public void setAdapter(ListAdapter adapter) {
    // 如果已经有了一个Adapter,那么就先注销该Adapter对应的观察者
    if (mAdapter != null && mDataSetObserver != null) {
        mAdapter.unregisterDataSetObserver(mDataSetObserver);
    }

    // 代码省略
    super.setAdapter(adapter);

    if (mAdapter != null) {
        mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
        mOldItemCount = mItemCount;
        // 获取数据的数量
        mItemCount = mAdapter.getCount();
        checkFocus();

        // 创建一个数据集观察者
        mDataSetObserver = new AdapterDataSetObserver();
        // 将这个观察者注册到Adapter中,实际上是注册到DataSetObservable
        mAdapter.registerDataSetObserver(mDataSetObserver);

        // 代码省略
    } else {
        // 代码省略
    }

    requestLayout();
}

当ListView的数据发生变化时,调用Adapter的notifyDataSetChanged()方法,这个方法又会调用DataSetObservable的notifyChanged()方法,这个方法会调用所有观察者(AdapterDataSetObserver)的onChange()方法,在onChange()方法中又会调用ListView重新布局的方法requestLayout()使得ListView刷新界面。

5. 观察者模式的应用

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