Android设计模式学习日记03--观察者模式

来源:互联网 发布:mysql注入语句大全 编辑:程序博客网 时间:2024/06/05 04:46

本次学习基于

Android设计模式系列(2)--SDK源码之观察者模式

观察者模式,是一种非常常见的设计模式,在很多系统中随处可见,尤其是涉及到数据状态发生变化需要通知的情况下。
本文以AbstractCursor为例子,展开分析。
观察者模式,Observer Pattern,是一个很实用的模式,本人曾经接触到的各种平台以及曾经参与项目中打印模板解释器中都用到了此模式。

1.意图
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
热门词汇:依赖 发布-订阅 事件 通知 更新 监听 

2.结构


这是一个最简单的观察者模式,目标对象能够添加和删除观察者,当自己某种状态或者行为发生改变时,可通过notify通知注册的观察者进行更新操作。
分析AbstractCursor的具体情况,我们发现实际工作有时需要对观察者进行统一管理,甚至观察者类型有很多种而又可以分成几个系列,这个时候是要复杂的多,通过合理的分层这个问题很好解决。下面根据具体情况,我们画出android中abstractCurosr中用到的观察者模式结构图:


观察者分成了两个系列。

3.代码
列举其中相关核心代码如下:

public abstract class AbstractCursor {    //定义管理器    DataSetObservable mDataSetObservable = new DataSetObservable();    ContentObservable mContentObservable = new ContentObservable();        //注册和卸载两类观察者    public void registerContentObserver(ContentObserver observer) {        mContentObservable.registerObserver(observer);    }    public void unregisterContentObserver(ContentObserver observer) {        // cursor will unregister all observers when it close        if (!mClosed) {            mContentObservable.unregisterObserver(observer);        }    }    public void registerDataSetObserver(DataSetObserver observer) {        mDataSetObservable.registerObserver(observer);            }    public void unregisterDataSetObserver(DataSetObserver observer) {        mDataSetObservable.unregisterObserver(observer);    }    //2类通知方法    protected void onChange(boolean selfChange) {        synchronized (mSelfObserverLock) {            mContentObservable.dispatchChange(selfChange);            if (mNotifyUri != null && selfChange) {                mContentResolver.notifyChange(mNotifyUri, mSelfObserver);            }        }    }    protected void notifyDataSetChange() {        mDataSetObservable.notifyChanged();    }}

  再看看Observable<T>类和DataSetObservable类:

public abstract class Observable<T> {    /**     * 观察者列表     */    protected final ArrayList<T> mObservers = new ArrayList<T>();    public void registerObserver(T observer) {        if (observer == null) {            throw new IllegalArgumentException("The observer is null.");        }        synchronized(mObservers) {            if (mObservers.contains(observer)) {                throw new IllegalStateException("Observer " + observer + " is already registered.");            }            mObservers.add(observer);        }    }    public void unregisterObserver(T observer) {        if (observer == null) {            throw new IllegalArgumentException("The observer is null.");        }        synchronized(mObservers) {            int index = mObservers.indexOf(observer);            if (index == -1) {                throw new IllegalStateException("Observer " + observer + " was not registered.");            }            mObservers.remove(index);        }    }        public void unregisterAll() {        synchronized(mObservers) {            mObservers.clear();        }            }}

  和

public class DataSetObservable extends Observable<DataSetObserver> {    /**     * 数据发生变化时,通知所有的观察者     */    public void notifyChanged() {        synchronized(mObservers) {            for (DataSetObserver observer : mObservers) {                observer.onChanged();            }        }    }    //... ... (其他方法)}

  观察者DataSetObserver类是一个抽象类:

public abstract class DataSetObserver {    public void onChanged() {        // Do nothing    }}

  所以我们具体看它的子类:

public class AlphabetIndexer extends DataSetObserver{    /*     * @hide 被android系统隐藏起来了     */    @Override    public void onChanged() {        //观察到数据变化,观察者做自己该做的事情        super.onChanged();        mAlphaMap.clear();    }}

  ContentObserver也是类似。

4.效果
(1).行为型模式
(2).目标和观察者间的抽象耦合(经典实现)。
(3).支持广播通信(相信这点android开发者看到后应该有启发吧)。
(4).注意意外的更新,这也是观察者更新进行管理的原因之一。

就像电影里面的,

犯罪分子交易总要派出一个或者几个小弟去具体一个地方盯梢 ,

这几个小弟就是观察者,

观察这个地方是否出现了异常,

一旦观察到情况就打印出来给你了

当然可以把他们都叫走


下面的代码 部分参考来自http://www.iteye.com/topic/102068/

Java代码  
  1. public interface Observer {  
  2.     /** 
  3.      * This method is called whenever the observed object is changed. An 
  4.      * application calls an <tt>Observable</tt> object's 
  5.      * <code>notifyObservers</code> method to have all the object's 
  6.      * observers notified of the change. 
  7.      * 
  8.      * @param   o     the observable object. 
  9.      * @param   arg   an argument passed to the <code>notifyObservers</code> 
  10.      *                 method. 
  11.      */  
  12.     void update(Observable o, Object arg);  
  13. }  
  14. }  

很好,这是一个接口,接口中就只有一个方法,update,方法中有两个参数,Observable和一个object,第一个参数就是被观察的对象,而第二个参数就得看业务需求了,需要什么就传进去什么。我们自己的观察者类必须实现这个方法,这样在被观察者调用notifyObservers操作时被观察者所持有的所有观察者都会执行update操作了(当然如果你override这个方法,你甚至可以指定何种情况下只执行某种observer了,是不是比较像责任链模式了)。 

  1. public class Observable {  
  2.     private boolean changed = false;  
  3.     private Vector obs;  
  4.      
  5.     //创建被观察者时就创建一个它持有的观察者列表,注意,这个列表是需要同步的。  
  6.     public Observable() {  
  7.     obs = new Vector();  
  8.     }  
  9.   
  10.     /** 
  11.      * 添加观察者到观察者列表中去 
  12.      */  
  13.     public synchronized void addObserver(Observer o) {  
  14.         if (o == null)  
  15.             throw new NullPointerException();  
  16.     if (!obs.contains(o)) {  
  17.         obs.addElement(o);  
  18.     }  
  19.     }  
  20.   
  21.     /** 
  22.      * 删除一个观察者 
  23.      */  
  24.     public synchronized void deleteObserver(Observer o) {  
  25.         obs.removeElement(o);  
  26.     }  
  27.   
  28.     /** 
  29.      * 通知操作,即被观察者发生变化,通知对应的观察者进行事先设定的操作,不传参数的通知方法 
  30.      */  
  31.     public void notifyObservers() {  
  32.     notifyObservers(null);  
  33.     }  
  34.   
  35.     /** 
  36.      * 与上面的那个通知方法不同的是,这个方法接受一个参数,这个参数一直传到观察者里,以供观察者使用 
  37.      */  
  38.     public void notifyObservers(Object arg) {  
  39.       
  40.         Object[] arrLocal;  
  41.   
  42.     synchronized (this) {  
  43.         if (!changed)  
  44.                 return;  
  45.             arrLocal = obs.toArray();  
  46.             clearChanged();  
  47.         }  
  48.   
  49.         for (int i = arrLocal.length-1; i>=0; i--)  
  50.             ((Observer)arrLocal[i]).update(this, arg);  
  51.     }  
  52. }  


Java代码  
  1. public class 武警Observer implements Observer{   
  2.     public void update(Observable o, Object arg) {  
  3.         System.out.println("观察到武警在路上了");  
  4.     }  
  5. }  

Java代码  
  1. public class 警察Observer implements Observer{  
  2.     public void update(Observable o, Object arg) {  
  3.         System.out.println("观察到警察在路上了");  
  4.     }  
  5. }  
Java代码  
  1. public class Subject extends Observable{  
  2.       
  3.     /** 
  4.      * 业务方法,一旦执行某个操作,则通知观察者 
  5.      */  
  6.     public void doBusiness(){  
  7.         if (true) {  
  8.             super.setChanged();  
  9.         }  
  10.         notifyObservers("现在还没有的参数");  
  11.     }  
  12.   
  13.       
  14.     public static void main(String [] args) {  
  15.         //创建一个被观察者  
  16.         Subject subject = new Subject();  
  17.           
  18.         //创建两个观察者  
  19.         Observer xxx警察Observernew 警察Observer();  
  20.         Observer xxx武警Observernew 武警Observer();  
  21.           
  22.         //把两个观察者加到被观察者列表中  
  23.         subject.addObserver(xxx警察Observer);  
  24.         subject.addObserver(xxx武警Observer);  
  25.           
  26.         //执行业务操作  如果里面有具体的参数  那么就可以观察者就会判断出是不是属于自己的了
  27.         subject.doBusiness();  
  28.     }  

0 0