剛開始學習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中可以運用在很多邏輯裏面,比如購買不一樣的商品,支付的時候選擇其中一款商品進行支付,支付成功的時候需要更新購物車。還有很多需要及時更新數據的時候也可以使用觀察者模式。