觀察者模式
1.定義
在對象之間定義一種一對多的依賴關系,使得當一個對象的狀態(tài)的發(fā)生改變時,依賴它的所有對象都會得到通知并被自動更新。觀察者模式也叫做發(fā)布訂閱模式。
觀察者模式通常有四個角色
AbstractSubject:抽象被觀察者。定義被觀察者必須實現(xiàn)的全部職責,且能夠動態(tài)的增加或取消觀察者。通常是一個抽象類。
public abstract class AbstractSubject {
/** 定義一個觀察者集合 **/
private Vector<AbstractObserver> observers = new Vector<>();
/**
* 添加一個觀察者
* @param observer
*/
public void addObserver(AbstractObserver observer) {
this.observers.add(observer);
}
/**
* 移除一個觀察者
* @param observer
*/
public void removeObserver(AbstractObserver observer) {
this.observers.remove(observer);
}
public void notifyAllObservers() {
for (AbstractObserver observer : observers) {
observer.run();
}
}
}
AbstractObserver:抽象觀察者。定義接收到通知時的動作。
public interface AbstractObserver {
/** 定義接收到通知時的動作 **/
void run();
}
Subject:被觀察者。實現(xiàn)自己的業(yè)務邏輯,定義對哪些事件進行通知。
public class Subject extends AbstractSubject {
public void doSomething() {
System.out.println("被觀察者具體業(yè)務邏輯");
super.notifyAllObservers();
}
}
Observer:觀察者。實現(xiàn)自己對通知的處理邏輯。
public class ObserverOne implements AbstractObserver {
@Override
public void run() {
System.out.println("觀察者ObserverOne接收到通知并處理!");
}
}
public class ObserverTwo implements AbstractObserver {
@Override
public void run() {
System.out.println("觀察者ObserverTwo接收到通知并處理!");
}
}
場景類
public class Client {
public static void main(String[] args) {
// 定義被觀察者
Subject subject = new Subject();
// 定義觀察者
AbstractObserver observerOne = new ObserverOne();
AbstractObserver observerTwo = new ObserverTwo();
// 觀察者監(jiān)視被觀察者
subject.addObserver(observerTwo);
subject.addObserver(observerOne);
subject.doSomething();
}
}
2.應用
2.1 優(yōu)點
- 觀察者與被觀察者之間是抽象耦合。兩者都容易擴展。
- 建立了一套觸發(fā)機制。
2.2 缺點
- 消息通知是順序執(zhí)行,當有多個觀察者時,開發(fā)和運行效率低,且一旦有一個觀察者卡殼會影響整個觸發(fā)鏈的執(zhí)行效率。該情況下考慮使用異步方式。
- 當多級觸發(fā)時,效率非常低。
2.3 使用場景
- 事件的多級觸發(fā)
- 跨系統(tǒng)消息交換,如消息隊列的處理機制。
2.4 注意事項
- 多級觸發(fā)鏈邏輯復雜,可維護性差。建議避免一個對象既是觀察者也是被觀察者。
- 觀察者異步觸發(fā)需要考慮線程安全及隊列問題。
3.擴展
JDK中提供了java.util.Observable實現(xiàn)類和java.util.Observer接口,可以用來很方便的實現(xiàn)觀察者模式。
優(yōu)化后的被觀察者
public class Subject extends Observable,AbstractSubject {
public void doSomething() {
System.out.println("被觀察者具體業(yè)務邏輯");
super.notifyAllObservers();
}
}
優(yōu)化后的觀察者
public class ObserverOne implements Observer {
public void update(Observable observable, Object object) {
System.out.println("觀察者ObserverOne接收到通知并處理!");
}
}
java.util.Observer要求update傳遞兩個參數(shù),被觀察者及數(shù)據(jù)傳輸對象(由被觀察者生成,由觀察者消費)。
觀察者實現(xiàn)快速響應的兩種方式。一是多線程技術,二是緩存技術。