觀察者模式封裝:SuperObservable

SuperObservable

其實android源碼里已經(jīng)有觀察者模式的封裝了:

package android.database;
import java.util.ArrayList;
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();
       }
   }
}

可以看到這是一個抽象類,主要提供了三個方法,用來注冊和注銷觀察者。使用起來就是繼承Observable,然后添加一些notify的方法來通知觀察者。DataSetObservable就是這么做的:

package android.database;

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();
            }
        }
    }
}

但是我也學著DataSetObservable這么用了一段時間,發(fā)現(xiàn)太麻煩了,

1488458379147.jpg

每次都要寫一個類繼承Observable,而且要要調(diào)用里面的方法都要寫一段像

synchronized (mObservers) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onInvalidated();
            }
        }

這樣的代碼,還有一個局限性就是傳參,都要在notify里寫一遍,所以勢必要封裝一下。

  • 不用每次寫一個類繼承Observable

  • 不用在調(diào)用Observer里的方法時都寫一個notify方法

    順著這個思路就是要 抽象類似mObservers.get(i).onChanged();的方法。
    于是便寫了一個接口,拿到了observer想干什么就干什么。

public interface Dispatcher<T> {
    void call(T t);
}

SuperObservale類誕生了:

public class SuperObservable<T> extends Observable<T> {

    public void notifyMethod(Dispatcher<T> dispatcher){

        synchronized (mObservers){
            for (int i = mObservers.size()-1; i >= 0; i--) {
                T t = mObservers.get(i);
                    if(dispatcher!=null){
                        dispatcher.call(t);
                    }
                }
            }
        }
    }
}

這樣只要在disatcher里寫好要調(diào)用的方法,就可以notify T(觀察者)中的任何方法了。每次只要new SuperObservable<T>便創(chuàng)建了一個被觀察者,簡單了不少。
考慮到有一個項目中會用到多次觀察者模式,便寫了一個SuperObservable的管理類:

public class SuperObservableManager {

    private static SuperObservableManager instance;

    private HashMap<Class,SuperObservable> mObservables;

    private SuperObservableManager() {
        mObservables = new HashMap<>();
    }

    public static SuperObservableManager getInstance(){
        if(instance==null){
            synchronized (SuperObservableManager.class){
                if(instance==null){
                    instance = new SuperObservableManager();
                }
            }
        }
        return instance;
    }

    /**
     * 添加被觀察者
     * @param observableName
     * @param superObservable
     * @param <Observer>
     *  利用泛型約束被觀察者superObservable:
     *  讓其只受Observer類型的觀察者觀察
     */
    public <Observer> void addObservable(Class<Observer>observableName,SuperObservable<Observer>superObservable){
        if(mObservables.containsKey(observableName)){
            throw new IllegalStateException("已添加過"+observableName.getSimpleName()+"類型的被觀察者!");
        }
        mObservables.put(observableName,superObservable);
    }
    /**
     * 獲取被觀察者
     * @param observableName
     * @return
     */
    public <Observer> SuperObservable<Observer> getObservable(Class<Observer> observableName){
        SuperObservable<Observer> superObservable = mObservables.get(observableName);

        if(superObservable==null){
            throw new IllegalStateException("未添加"+observableName.getSimpleName()+"類型的被觀察者!");
        }
        return superObservable;
    }
    /**
     * 移除被觀察者
     * @param observableName
     * @return
     */
    public SuperObservable removeObservable(Class observableName){
        return mObservables.remove(observableName);
    }
}

順便說一下我對觀察者模式的理解。觀察者模式本質(zhì)就是接口回調(diào),不過平時我們常用的是回調(diào)給一個對象,而觀察者一次性回調(diào)給多個對象。 可以解決 Activity與Fragment各種回調(diào),例如app登錄之后要把登錄狀態(tài)回調(diào)給諸多Activity與Fragment。

1488457866952.jpg

github 地址

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容