概述
它可以讓你時刻對對象了如指掌。
對象可以在運行時決定無論是否有消息通知它們。
觀察者模式的兩個組成部分是發布者和訂閱者。
在觀察者模式中發布者被稱為目標(subject)訂閱者被稱為觀察者(observer)。
目標和觀察者之間建立了某種聯系,目標中包含著各種數據,觀察者獲取這些數據,只要目標中有數據變動就通知觀察者。一個不相關的對象要想成為該目標的觀察者就必須要注冊成為該目標的觀察者,一個觀察者也只有通過注銷才能成為一個不相關的對象。這就是觀察者模式的主要思想。
觀察者模式的正式定義:它是一種1對多的依賴關系,即,一個目標多個觀察者,每當觀察者有變化時所有觀察者都會得到消息并可能發生相應的變化。在觀察者模式中觀察者和目標以及觀察者之間都是彼此獨立的。
P64給出了觀察者模式中的類圖設計。
在該圖中Subject是一個接口,它規定了注冊、注銷、通知觀察者等幾個方法。
Observer也是個接口,它規定了更新的行為。
Subject和Observer之間是1對多的關系。
要注冊成為Subject的對象就必須去實現Subject接口中的方法,此外,它還可以有設置自身狀態的存取器。
要成為Observer的對象就必須去實現Observer接口中的方法。
圖中的實箭頭代表關聯關系,虛箭頭代表實現。
觀察者模式提供了松散耦合,松散耦合可以使對象之間在互不知曉的情況下彼此互動。
在彼此互動的對象之間力求做到松散耦合
因為它最小化了對象之間的依賴關系,不會引起牽一發而動全身的情況。
P65列舉了它的好處。
JAVA本身有內置的觀察者模式API。
JAVA中的interface代表了一種抽象的功能,它不一定被實現但是它是某一類實現的通用載體,因此你想使用一類功能只需要引入一個interface的對象即可。它是具體實現細節的上一層次,是對軟件模塊之間聯系的把握。
代碼層面
被觀察者的setter是觸發觀察者刷新的關鍵所在,所以直接點說觀察者是基于setter實現的。被觀察者還必須維護一個觀察者的對象容器,訂閱和注銷就是對容器的操作而已。
類圖
依賴關系是個啥關系?
說得太官方了很抽象難懂,所以整點俗話。依賴關系就是A中有一部分用到了B,這就叫A依賴B。拿本例來說Subject中的方法參數是Observer類型的,于是說Subject是依賴Observer的。你中有我,但我中沒有你,則你依賴我。依賴方依賴被依賴方,依賴方在箭尾,被依賴方在箭頭。需要注意的是B并不屬于A,而所謂屬于是指B是A的成員。比方說你要做飯發現刀壞了,于是向別人借刀,于是你就依賴別人了,因為那刀不是你的。
使用
package com.company;
public class Main {
public static void main(String[] args) {
// write your code here
SubjectEntity subjectEntity = new SubjectEntity();
ObserverEntity observer1 = new ObserverEntity();
ObserverEntity observer2 = new ObserverEntity();
subjectEntity.addObserver(observer1);
subjectEntity.addObserver(observer2);
subjectEntity.setValue(1);
subjectEntity.setValue(9);
subjectEntity.removeObserver(observer2);
subjectEntity.setValue(2);
}
}
輸出
被觀察者設置值1
觀察者內部:1
觀察者內部:1
被觀察者設置值9
觀察者內部:9
觀察者內部:9
被觀察者設置值2
觀察者內部:2
Process finished with exit code 0
實現
Interface Subject
package com.company;
public interface Subject {
/**
* 因為觀察者實現Observer接口所以它也是個
* Observer對象了。
* @param observer
*/
void addObserver(Observer observer);//注冊成為觀察者
void removeObserver(Observer observer);//注銷。
void notifyObserver(int value);//通知觀察者
}
被觀察者實體SubjectEntity
package com.company;
import java.util.ArrayList;
import java.util.List;
public class SubjectEntity implements Subject {
private int value;
private List<Observer> observerList;//這個是必須的,用來存儲觀察者的。
public SubjectEntity() {
this.observerList = new ArrayList<>();
}
/**
* 這個也是必需的,因為它是觸發觀察者更新的
* 根本原因。
* @param value
*/
public void setValue(int value) {
System.out.println("被觀察者設置值" + value);
this.value = value;;
this.notifyObserver(this.value);
}
@Override
public void addObserver(Observer observer) {
if (!this.observerList.contains(observer))
observerList.add(observer);
}
@Override
public void removeObserver(Observer observer) {
if (this.observerList.contains(observer))
observerList.remove(observer);
}
@Override
public void notifyObserver(int value) {
for (Observer element:this.observerList)
element.updateObserver(value);
}
}
interface Observer觀察者
package com.company;
public interface Observer {
void updateObserver(int value);//更新觀察者。
}
觀察者實體ObserverEntity
package com.company;
public class ObserverEntity implements Observer {
public ObserverEntity() {
}
@Override
public void updateObserver(int value) {
System.out.println("觀察者內部:" + value);
}
}