盤點android中常見的設計模式(八) -- 觀察者模式

觀察者模式:

什麼是觀察者模式(Observer Pattern)?這裏我們舉個栗子:一隊警察部署在不同的位置觀察着犯罪分子的活動,當犯罪分子進行某個特定的行爲時,比如進行非法交易的時候,這隊在不同位置的警察同時出擊抓捕罪犯。這就是一種觀察者模式的詮釋。

觀察者模式定義了一種一對多的依賴關係,當被觀察者的狀態發生改變時,所有依賴於它的觀察者對象都會得到通知並作出自己的改變。這是一種行爲型模式。

觀察者主要有三大要素:被觀察對象、觀察者、他們之間的依賴方法。

觀察者模式的優點:

  • 觀察者和被觀察者是抽象耦合的
  • 建立了一套觸發機制。

 

Android中的使用:

我個人覺得觀察者模式可能android中應用最爲廣泛的一種設計模式了。別的不說,就按鈕的點擊事件onClick而言,就可以看做爲一種觀察者模式,這個過程中Button其實可以被看做是被觀察者,onClick事件可以看做是觀察者,而setOnClickListener方法就是它們之間的添加依賴關係的方法。當Button狀態發生改變時,即被點擊後,則通知了onClick完成更新。

另外大家所熟知的Rxjava其核心思想也是一種觀察者模式,最爲直觀地就是其五大基類之一的Observable,Observable通過subscribe方法去訂閱Observer來完成。通過命名我們也能知道,Observable是被觀察者,Observer是觀察者,而subscribe方法則是它們之間的依賴方法。(需要注意的是Rxjava中的觀察者模式觀察者與被觀察者的依賴關係是反着的,一般情況下應該是觀察者去subscribe被觀察者,這裏則是被觀察者去訂閱觀察者)。

接下來我們以一個簡單的例子來說明觀察者模式的簡單代碼實現,這個例子就是開頭所提到的警察抓捕小偷的過程。第一步:我們需要創建一個Observer的抽象類,用來抽象觀察者方法。

//被觀察者的抽象方法
public abstract class Observer {
    //當被觀察者狀態改變時,所有觀察者更新方法
    public abstract void update(boolean b);
}

第二步:創建被觀察者對象,即是例子裏的犯罪分子,並且定義一個集合observers用來存放所有的觀察者對象,定義一個布爾型的isCrime來保存被觀察者的狀態,即犯罪分子是否實施犯罪。

/**
 * 被觀察者對象 -- 犯罪分子
 */
public class Offender {
    //定義集合 存放所有觀察者對象
    private List<Observer> observers = new ArrayList<>();

    private boolean isCrime;

    public boolean isCrime() {
        return isCrime;
    }

    public void setCrime(boolean crime) {
        isCrime = crime;
        notifyAllObservers();
    }

    //訂閱方法 -- 添加與觀察者的依賴關係
    public void subscribe(Observer observer){
        observers.add(observer);
    }
    
    //通知所有觀察者更新
    public void notifyAllObservers(){
        for (Observer observer:observers) {
            observer.update(isCrime());
        }
    }
}

第三步:創建多個繼承自Observer的觀察者類並實現其update方法。

//觀察者 -- A警察
public class PuliceA extends Observer {

    @Override
    public void update(boolean b) {
        if (b){
            Log.i("ledding", "PuliceA 開始抓捕");
        }else{
            Log.i("ledding", "PuliceA 繼續觀察");
        }
    }
}


//觀察者 -- B警察
public class PuliceB extends Observer {

    @Override
    public void update(boolean b) {
        if (b){
            Log.i("ledding", "PuliceB 開始抓捕");
        }else{
            Log.i("ledding", "PuliceB 繼續觀察");
        }
    }
}

第四步:代碼中實現使用。

        //創建被觀察者-犯罪分子
        Offender offender = new Offender();
        //添加依賴關係
        offender.subscribe(new PuliceA());
        offender.subscribe(new PuliceB());

        //還沒有實施犯罪
        offender.setCrime(false);
        //實施犯罪
        offender.setCrime(true);

最後來看下打印的日誌是否實現了我們的預期。

打印日誌圖片

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章