文中項目代碼鏈接:https://github.com/BadWaka/WakaPedometer
一.觀察者模式簡介
1.定義:觀察者模式(有時又被稱為模型-視圖(View)模式、源-收聽者(Listener)模式或從屬者模式)是軟件設計模式的一種。在此種模式中,一個目標物件管理所有相依於它的觀察者物件,並且在它本身的狀態改變時主動發出通知。這通常透過呼叫各觀察者所提供的方法來實現。此種模式通常被用來實現事件處理系統。
2.三要素:觀察者,被觀察者,事件「訂閱」。
3.UML圖:
其實,說白了,觀察者模式就是一個一對多的消息的發布訂閱關系。在這個模式中,通常是有一個被觀察者,我們可以把它理解為消息的發布者;若干個觀察者,可以理解為消息的訂閱者。舉一個生活中的例子:微信公眾號,大家一定或多或少的都關注過幾個微信公眾號,每次公眾號發布的內容有更新的時候,訂閱號頁面里都會將這個公眾號置頂並加紅點提示。這就是一個典型的觀察者模式的應用。一個公眾號就是一個被觀察者,用戶通過訂閱操作與被觀察者建立聯系,這個用戶就成了觀察者。
二.Java中的觀察者模式及具體應用
1.Java中的觀察者模式簡介:
在Java中,要應用觀察者模式,觀察者要實現java.util.Observer接口;被觀察者要繼承java.util.Observable類。
在這個基礎上,觀察者要重寫Observer接口中的update()方法。觀察者向被觀察者訂閱事件是通過調用addObservers()方法來實現的。
2.觀察者和被觀察者的簡單代碼
(1)觀察者
//觀察者,需要用到觀察者模式的類需實現此接口 public interface Observer{ void update(Object...objs);
}
(2)被觀察者
public abstract class Observable<T> { public final ArrayList<T> observerList = new ArrayList<>(); //注冊觀察者對象 public void registerObserver(T t) { checkNull(t); observerList.add(t); } //注銷觀察者對象 public void unRegisterObserver(T t) { checkNull(t); observerList.remove(t); } //判斷觀察者對象是否為空 private void checkNull(T t) { if (t == null) { throw new NullPointerException(); } } //通知觀察者 public abstract void notifyObservers(Object... objects); }
3.觀察者模式在Java中的應用實例
以下實例是在一個AndroidAPP中實現一個計步器功能。在Service類中有一個步數變量step,Activity類中需要動態監聽step變量的變化,並根據其更新UI。由於這個功能中用到了發布訂閱,所以應使用觀察者模式。在這里Activity為觀察者,Service為被觀察者。
(1)觀察者代碼:
//觀察者實現Observer接口並重寫update()方法。 public class PedometerFragment extends Fragment implements Observer { @Override public void update(Observable observable, Object data) { } }
(2)被觀察者代碼:
//被觀察者繼承Observable類 public class StepObservable extends Observable { //單例 private static StepObservable instance = null; public static StepObservable getInstance() { if (null == instance) { instance = new StepObservable(); } return instance; } //通知觀察者更新數據 public void notifyStepChange(int step) { setChanged();//設置changeFlag notifyObservers(step);//通知觀察者 } }
(3)訂閱事件
//觀察者調用addObserver()向被觀察者訂閱事件 //項目中,這個步驟添加到Activity類的onResume()函數中 public void onResume() { super.onResume(); //訂閱操作 StepObservable.getInstance().addObserver(this); }
(4)更新數據
//被觀察者Service更新 private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); //.. //得到當前步數 currentStep = step; //由於步數改變,被觀察者更新數據 StepObservable.getInstance().notifyStepChange(currentStep); //.. } } //觀察者Activity更新 @Override //收到notifyObservers()方法的通知,調用update()函數,更新數據 public void update(Observable observable, Object data) { int step = (int) data; Snackbar.make(roundProgressBar, "step=" + step, Snackbar.LENGTH_SHORT).show(); Log.i(TAG, "step=" + step); }
(5)取消訂閱
//在Activity中的onpause()方法中實現取消訂閱的代碼 @Override public void onPause() { super.onPause(); //觀察者從被觀察者隊列中移除 StepObservable.getInstance().deleteObserver(this); }
三.總結
綜上所述,Java編程中需要大量應用觀察者模式的模型。觀察者模式作為一種十分常用的設計模式,為我們的編寫程序提供了便利。最后想總結一下觀察者模式的優缺點。
優點:觀察者與被觀察者之間是一個輕度的關聯關系,體現了模塊的高內聚,低耦合。因此對於觀察者和被觀察者來說,要進行擴展就比較簡單了。被觀察者並不需要認識任何一個具體的觀察者。它只需要提供一個觀察者共同的接口即可。提高代碼的可復用性。
缺點:在狀態變化,觀察者通知被觀察者的時候,如果觀察者過多,那么可能導致消息的傳送失去實時性。