版權宣告:本文為 Codeagles 原創文章,可以隨意轉載,但必須在明確位置註明出處!!!
###觀察者模式 什麼是觀察者模式?觀察者模式(Observer Pattern)就是一種 “釋出者-訂閱者” 的模式。也被稱為 “模型-檢視”模式、“源-監聽者”模式等。工作原理:由一個目標物件來管理所有依賴與它的觀察者物件,並且當這個目標物件***自身***發生改變時,會***主動***向它的觀察者們發出通知。
關鍵字:被觀察的目標自身、主動發出通知。
想要用觀察者模式,那就要知道這麼幾個問題:
- 為什麼要用
- 有什麼優點
- 有什麼缺點
- 怎麼用
之所以叫做淺談設計模式,是因為設計模式是一種思想,一種程式碼結構,它出自於眾多人的經驗,相對來說也很靈活,只是中心思想是不變的,筆者只能儘量舉例講的通俗易懂點,當然功力有限,還需看官多理解,放在自己的專案中,或者實際體驗中。
- 為什麼用?當然是因為一個物件改變了狀態,然後通知其他物件,之後怎麼辦那就是設計者的事情了。 應用案例其實也很多,比如按鍵新增監聽事件(Listener)。當然,對AWT、Swing比較陌生的。
舉個生活中的例子,訂飛機票,飛機什麼時候起飛,所有買票的乘客都在看著,那麼所有的乘客就是觀察者,他們需要觀察飛機的動態,而飛機就是目標物件,當飛機起飛的前一天,航空公司會給乘坐該飛機的所有乘客發一條簡訊:“飛機明天將於幾點幾分起飛,巴拉巴拉。。。”,這個時候所有的觀察者都會接到簡訊(目標物件主動傳送的通知),那麼乘客就知道飛機的動態了。
- 有什麼優點?可能太好理解,觀察者和被觀察者是抽象耦合的關係,雖然是耦合但是是低耦合,其次它可以監聽觸發事件嘛,觀察不就是為了知道我什麼時候行動嘛。
- 有什麼缺點?其實也很明顯。
- 一個物件的所有的觀察者都需要被通知,時間成本很高。
- 在這個模式中,觀察者只知道目標物件發生了變化,至於怎麼發生的它們是不知道的。
- 還有別的缺點,理解不到,功力太淺,暫不寫出。
- 怎麼用? ####Talk is cheap, show me the code. ####Subject類
package ObserverPattern;
import java.util.ArrayList;
import java.util.List;
public class Subject {
//觀察者列表
private List<Observer> observers = new ArrayList<Observer>();
//設定狀態,就是單純了讓Subject改變一下
private int state;
//setter and getter
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
//設定狀態,主動通知所有觀察者
notifyAllObservers();
}
//向觀察者列表中新增觀察者
public void addObservers(Observer ob){
observers.add(ob);
}
//通知所有觀察者
public void notifyAllObservers() {
for(Observer ob:observers){
//觀察者作出響應
ob.make_response();
}
}
}
複製程式碼
####Obeserver抽象類
package ObserverPattern;
public abstract class Observer {
//為觀察者的實體類做鋪墊,為了讓子類可以直接與Subject繫結
protected Subject subject;
public abstract void make_response();
}
複製程式碼
####FirstObserver的觀察者實體類
package ObserverPattern;
public class FirstObserver extends Observer{
//與Subject進行繫結
public FirstObserver(Subject sub){
this.subject=sub;
//開始監聽
this.subject.addObservers(this);
}
@Override
public void make_response() {
System.out.println("觀察者001,我的作用是輸出物件的改變狀態:"+subject.getState());
}
}
複製程式碼
####SecondObserver的觀察者實體類
package ObserverPattern;
public class SecondObserver extends Observer {
// 與Subject進行繫結
public SecondObserver(Subject sub) {
this.subject = sub;
// 開始監聽
this.subject.addObservers(this);
}
@Override
public void make_response() {
System.out.println("觀察者002,我的作用是將目標物件的狀態碼轉換成二進位制:"+Integer.toBinaryString(subject.getState()));
}
}
複製程式碼
####ObserverPattern的Demo
package ObserverPattern;
public class ObserverPattern {
public static void main(String[] args) {
Subject subject = new Subject();
FirstObserver fo= new FirstObserver(subject);
SecondObserver so =new SecondObserver(subject);
System.out.println("第一次設定狀態碼:520");
subject.setState(520);
System.out.println("第二次更改狀態碼:1314");
subject.setState(1314);
}
}
複製程式碼
####輸出結果:
第一次設定狀態碼:520
觀察者001,我的作用是輸出物件的改變狀態:520
觀察者002,我的作用是將目標物件的狀態碼轉換成二進位制:1000001000
第二次更改狀態碼:1314
觀察者001,我的作用是輸出物件的改變狀態:1314
觀察者002,我的作用是將目標物件的狀態碼轉換成二進位制:10100100010
複製程式碼
###總結 到這裡就結束了,本文講的是思路以及簡單原理,如果有問題,請在下面留言。還有就是強調一句,JAVA 中已經有了對觀察者模式的支援類。使用該模式需要注意,如果程式順序執行時,有一個觀察者錯誤,程式就會掛掉了,這個也不難想象。舉得例子,也有可能不太恰當,有好的例子也歡迎在留言區貼出來,一起談論。