前言
對于設計模式的學習,作者一開始是拒絕的。因為作者的Java基礎和Android基礎很爛。想著補一下Java坑,做做App練習,鞏固基礎,但是糾結了半天還是選擇看看設計模式,畢竟還年輕,瞎搞唄。大致瀏覽了一下設計模式,發(fā)現(xiàn)確實很難懂。借著這個機會,我就想把自己的設計模式學習歷程記錄下來,希望能對迷茫的朋友有所幫助。當然了,新手上路,錯誤難免,請多指教!
觀察者模式
-
定義
裝逼式:定義對象之間一種一對多的依賴關系,使得每當一個對象改變狀態(tài),則所有依賴于它的對象都會得到通知并被自動更新。
正常點說:幾個對象去觀察一個對象的狀態(tài),這一個對象狀態(tài)發(fā)生改變時,會通知觀察它的那幾個對象,這幾個對象觀察到被觀察對象狀態(tài)發(fā)生變化了,然后自己就會做一些事情。當然,從這里就引出了兩個關鍵類——Observer(觀察者)、Subject(被觀察者)

-
應用
當對象間存在一對多關系時,則使用觀察者模式(Observer Pattern)。
比如,當一個對象被修改時,則會自動通知它的依賴對象。觀察者模式屬于行為型模式。
-
實際操作
意圖:定義對象間的 一對多 的關系。
用途:目標對象的狀態(tài)改變,所有的依賴對象(觀察者對象)得到通知。
實例:1、拍賣的時候,拍賣師觀察最高標價,然后通知給其他競價者競價。 2、西游記里面悟空請求菩薩降服紅孩兒,菩薩灑了一地水招來一個老烏龜,這個烏龜就是觀察者,他觀察菩薩灑水這個動作。 3、顧客在訂奶站定牛奶,訂奶站的人員只需保證牛奶送到訂奶站,并通知顧客前來領取而不管顧客會把牛奶拿去喝還是洗臉;顧客接到訂奶站的工作人員的通知,就去取牛奶,但并不關心他們是怎樣把牛奶送到訂奶站的。4、快遞員送快遞,打電話叫顧客領包裹。等等。
利弊: 利:1、觀察者和被觀察者是抽象耦合的。 2、建立一套觸發(fā)機制。弊:1、如果一個被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。 2、如果在觀察者和觀察目標之間有循環(huán)依賴的話,觀察目標會觸發(fā)它們之間進行循環(huán)調用,可能導致系統(tǒng)崩潰。 3、觀察者模式?jīng)]有相應的機制讓觀察者知道所觀察的目標對象是怎么發(fā)生變化的,而僅僅只是知道觀察目標發(fā)生了變化(理論的東西太死板,不好直觀地反映問題,遇到具體的代碼再說吧。)。
注意:
(1)在抽象類里有一個 ArrayList 存放觀察者們。
(2)JAVA 中已經(jīng)有了對觀察者模式的支持類。JDK中提供的java.util.Observable實現(xiàn)類和java.util.Observer接口。
(3)避免循環(huán)引用。
(4)如果順序執(zhí)行,某一觀察者錯誤會導致系統(tǒng)卡殼,一般采用異步方式。
-
使用
Android中的觀察者實現(xiàn)Observer接口,被觀察者繼承Obervable類
- 觀察者MyObserver實現(xiàn)Observer 接口。
- 被觀察者MyObservable繼承Observable 類。
- 觀察者MyObserver向被觀察者 MyObservable 訂閱事件(將觀察者MyObserver添加到被觀察者MyObservable里面去)。
- 被觀察者MyObservable數(shù)據(jù)有改變,通知觀察者MyObserver相應的數(shù)據(jù)有改變,請作出相應的操作。(核心操作)
- 觀察者MyObserver向被觀察者 MyObservable取消訂閱事件(將觀察者MyObserver從被觀察者MyObservable中移除)。
-
入坑
看了部分資料,踩坑一步一步寫了點:
觀察者類(Object):
/**
* @author bruno
* @date: 2016/6/1
*
* TODO <>觀察者類,實現(xiàn)Observer的接口。</>
*/
public abstract class MyObserver implements Observer {
@Override
public void update(Observable observable, Object data) {
}
}
問:觀察者必須是抽象類么?
被觀察類(Subject):
/**
* @author bruno
* @date: 2016/6/1
*
* TODO <>被觀察者類,繼承Observable</>
*/
public class MyObservable extends Observable {
//單例模式
private volatile static MyObservable instance = null;
private MyObservable() {
}
public static MyObservable getInstance() {
if (instance == null) {
synchronized (MyObservable.class) {
if (instance == null) {
instance = new MyObservable();
}
}
}
return instance;
}
public void notifyDataChange(Data data) {
//這是Observable的兩個重要方法,數(shù)據(jù)改變和觀察者的改變
setChanged();
notifyObservers(data);
}
}
被觀察者類直接繼承Observable就行,這里使用了單例模式(雙重校驗鎖)。關于單例模式,了解過一點,但是現(xiàn)在沒怎么運用,所以還只是停留在概念上。這里有一篇不錯的文章,如有問題,還望讀者指出。
Data類:
/**
* @author bruno
* @date: 2016/6/1
*
* TODO <>Data數(shù)據(jù)類</>
*/
public class Data {
private int dataChange;
public Data() {
}
public int getDataChange() {
return dataChange;
}
public void setDataChange(int dataChange) {
this.dataChange = dataChange;
}
}
這個沒什么解釋的,模擬數(shù)據(jù)。
Activity:
public class MainActivity extends AppCompatActivity {
private MyObserver myObserver = new MyObserver() {
@Override
public void update(Observable observable, Object data) {
super.update(observable, data);
//觀察者接受到被觀察者的通知,來更新自己的數(shù)據(jù)操作。
Data mData = (Data) data;
Log.e("MainActivity", "mData+++++++++++++" + mData.getDataChange());
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//模擬被觀察者數(shù)據(jù)改變,更新數(shù)據(jù)。
Data mData = new Data();
mData.setDataChange(0);
MyObservable.getInstance().notifyDataChange(mData);
}
@Override
protected void onResume() {
super.onResume();
//觀察者往被觀察者中添加訂閱事件。
MyObservable.getInstance().addObserver(myObserver);
}
@Override
protected void onPause() {
super.onPause();
//觀察者從被觀察者隊列中移除
MyObservable.getInstance().deleteObserver(myObserver);
}
}
初探這坑不淺,還得慢慢踩。請多指教!
-
參考資料
Android 中的觀察者模式
Android 實現(xiàn) listener: Observer pattern (觀察者模式)
歡迎大家討論交流指出問題。