概念
觀察者模式:定義了物件之間的一對多依賴,這樣一來,當一個物件狀態改變時,他的所有依賴者都會收到通知並自動更新。
觀察者模式涉及的角色
主題(Subject):一對多中的一,持有資料,當資料更新時,通知已註冊的觀察者
觀察者(Observer):一對多中的多,接收主題資料做出響應
舉個例子
一位媽媽(主題)有兩個孩子,取名為小愛和小冰(觀察者)。一天小愛和小冰都去找她們的朋友玩,當到了吃飯的時間,媽媽總會打電話通知她們回來吃飯(孩子預設在媽媽那註冊為觀察者registerObserver),但中途小冰打電話和媽媽說:“不回來吃飯了,和朋友吃”(取消觀察者這角色removeObserver)。所以最後,只有小冰收到媽媽的通知,並告訴她今天買了你喜歡吃的雞腿(notifyObserver)。
程式碼
Person.java,Mother和Child都繼承這個類[這步和講述觀察者模式沒什麼關係]
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Mother.java
public class Mother extends Person implements Subject{
/**
* 她要通知的孩子
*/
private ArrayList<Observer> children = new ArrayList<>();
/**
* 通知的內容
*/
private String message;
public Mother(String name) {
super(name);
}
@Override
public void registerObserver(Observer observer) {
children.add(observer);
}
@Override
public void removeObserver(Observer observer) {
children.remove(observer);
}
@Override
public void notifyObserver() {
children.forEach(observer -> observer.message(message));
}
public void sendMessage(String message) {
this.message = message;
// 通知她們
notifyObserver();
}
}
Child.java
public class Child extends Person implements Observer{
public Child(String name) {
super(name);
}
@Override
public void message(String m) {
System.out.println(getName() + "收到的訊息:" + m);
}
}
Main.java
public class Main {
public static void main(String[] args) {
Mother mother = new Mother("媽媽");
Child xiaoBing = new Child("小冰");
Child xiaoAi = new Child("小愛");
// 孩子都是親生的,吃飯時叫她們
mother.registerObserver(xiaoBing);
mother.registerObserver(xiaoAi);
mother.sendMessage("飯煮好了,回來吃飯,買了你們想吃的雞腿");
System.out.println("------------------分割線-----------------------");
// 小愛說不回來吃了,取消通知她
mother.removeObserver(xiaoAi);
mother.sendMessage("飯煮好了,回來吃飯,買了你們想吃的雞腿");
}
}
執行結果:
小冰收到的訊息:飯煮好了,回來吃飯,買了你們想吃的雞腿
小愛收到的訊息:飯煮好了,回來吃飯,買了你們想吃的雞腿
------------------分割線-----------------------
小冰收到的訊息:飯煮好了,回來吃飯,買了你們想吃的雞腿
優點
主題與觀察者之間鬆耦合。有新型別的觀察者出現時,主題的程式碼不需要修改。假如我們有一個新的具體類需要當觀察者,我們不需要為了相容新型別而修改主題的程式碼,所有要做的就是在新的類裡實現此觀察者介面,然後註冊成觀察者即可。
就好比如上面例子,如果國家不久的將來開放三胎政策,媽媽又生了個小娜,媽媽不需要修改自身的邏輯。如果孩子要回家吃飯就實現Observer介面,媽媽那registerObserver就OK。