一、什麼是觀察者模式
觀察者定義了一種一對多的依賴關係,當一個主題(Subject)對象狀態發生變化時,所有依賴它的相關對象都會得到通知並且能夠自動更新自己的狀態,這些依賴的對象稱之爲觀察者(Observer)對象這類似於發佈/訂閱模式。
觀察者模式中的主題對象,會維持着一個依賴它的觀察者對象列表,當主題對象狀態發生改變時,主題對象便會調用這個列表中所有觀察者對象的方法。
觀察者模式一般用在分佈式時間處理系統,它也是流行的MVC模型的核心設計模式。
二、觀察者模式中的角色
觀察者模式主要涉及到三個組件:Subject、Observer、ConcreteObserver
- 主題(Subject):保存了所有觀察者的引用,並供註冊、刪除觀察者的接口,提供自己狀態變化觸發所有觀察者更新的方法
- 觀察者(Observer):定義了更新自己狀態的接口
- 具體觀察者( ConcreteObserver):具體實現觀察者接口,使自己的狀態和主題狀態一致
三、代碼實例
1. 主題對象類
import java.util.ArrayList;
import java.util.List;
public class Subject {
//主題對象維持着一個依賴它的觀察者對象列表
private List<Observer> observers = new ArrayList<Observer>();
//主題對象的狀態
private int state;
//當主題對象狀態變化時,調用所有觀察者對象的方法
public void setState(int state) {
this.state = state;
notifyAllObservers();
}
//調用所有依賴它的觀察者的方法
public void notifyAllObservers(){
for (Observer observer : observers) {
observer.update(state);
}
}
//主題對象也可以註冊、和刪除依賴它的觀察者對象
public void attach(Observer observer){
observers.add(observer);
}
public int getState() {
return state;
}
}
2. 觀察者接口
public abstract class Observer {
public abstract void update(int state);
}
3. 具體的觀察者
public class ConcreteObserverA extends Observer{
@Override
public void update(int state) {
System.out.println( "ConcreteObserverA get state change event: " + state );
}
}
public class ConcreteObserverB extends Observer{
@Override
public void update(int state) {
System.out.println( "ConcreteObserverA get state change event: " + state );
}
}
最後寫一個測試類測試一下
public class ObserverPatternDemo {
public static void main(String[] args) {
//初始化主題對象
Subject subject = new Subject();
//註冊觀察者對象到主題對象
ConcreteObserverA ConcreteObserverA=new ConcreteObserverA();
ConcreteObserverB ConcreteObserverB=new ConcreteObserverB();
subject.attach(ConcreteObserverA);
subject.attach(ConcreteObserverB);
//主題對象狀態發生變化
subject.setState(20);
}
}
我們看一下運行結果:
ConcreteObserverA get state change event: 20
ConcreteObserverA get state change event: 20
當主題對象狀態發生改變,兩個註冊的觀察者都收到了通知。
四、總結
其實觀察者模式很簡單,其核心內涵依然是用面向對象思想思考問題而非面向過程思想,面向接口編程,解耦合依賴。
但是觀察者模式也有缺點,觀察者模式是一種常用的鏈式觸發機制,由於是鏈式觸發,當觀察者比較多的時候,性能問題是比較令人擔憂的。並且,在鏈式結構中,比較容易出現循環引用的錯誤,造成系統假死。