觀察者模式--農民的故事

剛開始學習Java的就接觸觀察者模式了,但是總是不太能理解這種模式或者理解的一點不深刻,特別容易忘記。最近搞Android總是遇到RxJava,RxAndroid,畢竟RxJava+RxAndroid+okHttp太火了。爲了學習這種框架就得重新搞一下Java的觀察者模式了。首先用Java講一個農民的故事:
話說桃花源的農民都很聰明,耕種的時候都會在老天下雨的時候開始耕種,這樣種出來的莊稼會有更好的收成。所以種瓜的農民伯伯、種豆的農民阿姨天天都在觀察着老天爺。(老天爺:被觀察者)老天爺一下雨,農民伯伯就馬上種瓜、農民阿姨馬上種豆。(注意:農民伯伯、農民阿姨兩人可能基本不認識,兩者一點關係都沒有)。

首先定義一下農民的行爲(觀察者)

package com.lxz;
/**
 * 描述:觀察者(農民)
 * 作者:Linxz
 * 郵箱:[email protected]
 * 時間: 2017年4月14日 上午11:05:32
 * 版本:1.0
 */
public interface Observer {

    /**標記當前觀察者是誰*/
    public void setName(String name);

    /**老天下雨的時候農民的行爲*/
    public void farmerDo(Object message);

}

被觀察者(老天爺)

package com.lxz;
/**
 * 描述:被觀察者(老天爺)
 * 作者:Linxz
 * 郵箱:[email protected]
 * 時間: 2017年4月14日 上午11:07:52
 * 版本:1.0
 */
public interface Observerable {

    /**訂閱(將該農民放到觀察者的隊伍中)*/
    public void attach(Observer observer);

    /**取消訂閱(改農民不再觀察我)*/
    public void detach(Observer observer);

    /**下雨了:通知觀察者*/
    public void notifyObservers(Object message);

}

定義好了農民跟老天爺的行爲之後,創建農民跟老天爺實體:
農民實體,農民具備農民的基本屬性跟行爲(農民的名稱,觀察老天爺下雨)

package com.lxz;
/**
 * 描述:
 * 作者:Linxz
 * 郵箱:[email protected]
 * 時間: 2017年4月14日 上午11:20:16
 * 版本:1.0
 */
public class Farmer implements Observer{

    /**標識我是種瓜的農民伯伯還是種豆的農民阿姨*/
    private String name;

    @Override
    public void setName(String name) {
        this.name=name;
    }

    /**農民的行爲*/
    @Override
    public void farmerDo(Object message) {
       System.out.println(message+":"+name);        
    }
}

然後再定義下雨的老天爺(被觀察者:具備下雨行爲),因爲老天爺只有一個,所以我這裏定義了單利模式(不是單利也行)

package com.lxz;
import java.util.ArrayList;
import java.util.List;
/**
 * 描述:
 * 作者:Linxz
 * 郵箱:[email protected]
 * 時間: 2017年4月14日 上午11:27:33
 * 版本:1.0
 */
public class God implements Observerable{

    private static God instance;

    /**收集全部的觀察者*/
    private static List<Observer> observers=new ArrayList<>();

    private God(){}

    public static God newInstance(){
       if(instance==null){
           instance=new God();
       }
       return instance;
    }

    /**誰在觀察我*/
    @Override
    public void attach(Observer observer) {
        observers.add(observer);    
    }

    /**誰不再觀察我了*/
    @Override
    public void detach(Observer observer) {
        observers.remove(observer);
    }

    /**我開始下雨了*/
    @Override
    public void notifyObservers(Object message) {
        for(Observer observer:observers){
            observer.farmerDo(message);
        }
    }

}

到此已經將農民跟老天爺實體定義好了,那現在老天爺就準備下雨了:

package com.lxz;
/**
 * 描述:
 * 作者:Linxz
 * 郵箱:[email protected]
 * 時間: 2017年4月14日 上午11:36:05
 * 版本:1.0
 */
public class ObserverExeceute {

    public static void main(String[] args) {

        /**老天爺*/
        Observerable god=God.newInstance();

        /**農民伯伯*/
        Observer farmerA=new Farmer();
        farmerA.setName("農民伯伯馬上種瓜");
        god.attach(farmerA);

        /**農民阿姨*/
        Observer farmerB=new Farmer();
        farmerB.setName("農民阿姨馬上種豆");
        god.attach(farmerB);

        /**老天爺下雨了*/
        god.notifyObservers("下雨了");

    }

}

這裏寫圖片描述

從結果可以看到,老天爺一下雨,農民伯伯就去種瓜、農民阿姨就去種豆了。從結果也能很好地看到觀察者模式可以很好地進行解耦,農民伯伯、農民阿姨都對老天爺進行了觀察,下雨了時候他們的行爲卻不一樣。也就是說,老天爺只管通知觀察者我下雨了,至於具體的操作就由他們自由去決定,而觀察者跟觀察者之間可以沒有一丁點關係。在程序中,有時候一個類的數據改變了,可能會觸發好幾個類的數據改變,這時候使用觀察者模式就能很好地解決問題。

那麼在Android開發的過程中有哪些情況可以使用觀察者模式呢?舉個簡單的例子。每個APP應用程序都會有登錄註冊邏輯。比如註冊要涉及:填寫手機號(第一個頁面)—>接收驗證碼(第二個頁面)–>設置密碼(第三個頁面)—>註冊(APP主頁),進入APP主頁的時候就應該把用戶的註冊登錄頁面銷燬了。這種邏輯很多人會使用帶值跳轉,頁面銷燬時會往上一個頁面返回一個標識要銷燬頁面的值,在onActivityForResult中進行頁面銷燬,如下:
Register1Activity:
這裏寫圖片描述

Register2Activity:
這裏寫圖片描述

Register3Activity
這裏寫圖片描述

這樣就能把註冊流程的全部頁面給銷燬了,很多人都是這麼幹的。有的人也會使用廣播,註冊成功之後發送一個廣播,註冊流程的頁面接收到這個廣播之後就銷燬頁面。

現在認識了觀察者模式可以使用觀察者模式實現,註冊流程的Activity都實現觀察者Observer,註冊成功之後被觀察者通知觀察者註冊成功,銷燬頁面(和上面農民的故事一個原理)。
首先定義觀察者接口:

package linxz.com.streamlet.interfaces;
/**
 * 功能描述:
 * 作者:Linxz
 * E-mail:[email protected]
 * 版本信息:V1.0.0
 * 時間:2017年04月14日  9:39.
 **/
public interface Observer {

    /**標識是哪個實體類(可以不要這個方法)*/
    public void setName(String name);

    /**該實體類需要更新數據(不需要傳遞數據的情況下此方法可以爲無參)*/
    public void updateDate(Object object);
}

被觀察者接口:

package linxz.com.streamlet.interfaces;
/**
 * 功能描述:
 * 作者:Linxz
 * E-mail:[email protected]
 * 版本信息:V1.0.0
 * 時間:2017年04月14日  9:41.
 **/
public interface Observable {

    /**訂閱*/
    public void attach(Observer observer);

    /**取消訂閱*/
    public void detach(Observer observer);

    /**通知觀察者更新數據*/
    public void notifyObservers(Object object);
}

定義一個類專用來執行觀察、取消觀察、通知更新:

package linxz.com.streamlet.interfaces;
import java.util.ArrayList;
import java.util.List;
/**
 * 功能描述:
 * 作者:Linxz
 * E-mail:[email protected]
 * 版本信息:V1.0.0
 * 時間:2017年04月14日  10:14.
 **/
public class ObserverExecute implements Observable{

    private static ObserverExecute instance;
    /**蒐集全部的觀察者*/
    private static List<Observer> observers=new ArrayList<>();

    private ObserverExecute(){}

    public static ObserverExecute newInstance(){
        if (instance==null){
            instance=new ObserverExecute();
        }
        return instance;
    }

    /**訂閱*/
    @Override
    public void attach(Observer observer) {
        observers.add(observer);
    }

    /**取消訂閱*/
    @Override
    public void detach(Observer observer) {
        observers.remove(observer);
    }

    /**通知更新數據或者銷燬頁面*/
    @Override
    public void notifyObservers(Object object) {
        for (Observer observer:observers){
            observer.updateDate(object);
        }
    }
}

註冊流程的Activity都實現觀察者接口,並執行訂閱,觀察註冊成功行爲:
這裏寫圖片描述

實現的接口的方法中對頁面進行銷燬:
這裏寫圖片描述

當然Activity銷燬的時候要執行取消訂閱
這裏寫圖片描述

註冊流程的Activity都這麼操作成爲一個觀察者。

註冊成功之後對通知全部的觀察者註冊成功:
這裏寫圖片描述

就這樣,註冊流程的頁面也會跟着銷燬了。這種流程其實歸根結底還是把註冊流程的Activity存儲起來,註冊成功了就進行銷燬。

觀察者模式在Android中可以運用在很多邏輯裏面,比如購買不一樣的商品,支付的時候選擇其中一款商品進行支付,支付成功的時候需要更新購物車。還有很多需要及時更新數據的時候也可以使用觀察者模式。

發佈了38 篇原創文章 · 獲贊 17 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章