什麼是觀察者模式
觀察者模式:定義物件之間的一對多依賴,當一個物件的改變狀態時,它的依賴者都會收到通知並自動更新。這裡就用報社、人來分析,如果有人想看報紙就可以向報社訂閱,如果已經訂閱的人不想看報紙可以向報社登出,而對於報社而言,它只會把報紙發給訂閱的人群,這裡的報社就是觀察者模式中的主題(Subject),人就是觀察者(Observer),觀察者向主題註冊自己就可以在主題改變時收到通知。
觀察者模式UML圖
程式碼實現
/**
* 觀察者模式的主題,用於註冊、移除、通知觀察者
*/
public interface Subject {
/**
* 新增觀察者
*/
void registerObserver(Observer observer);
/**
* 移除觀察者
*/
void removeObserver(Observer observer);
/**
* 通知觀察者
*/
void notifyObserver(String newspaperName);
}
/**
* 觀察者介面類
*/
public interface Observer {
/**
* 被通知時做的操作
*/
void update(String newspaperName);
}
上面時觀察者模式的兩個核心類,下面時具體的應用,首先是主題實現類-NewspaperOffice,observerList 儲存所有的觀察者,
import java.util.ArrayList;
import java.util.List;
public class NewspaperOffice implements Subject{
private List<Observer> observerList = new ArrayList<>();
@Override
public void registerObserver(Observer observer) {
observerList.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observerList.remove(observer);
}
/**
* 通知觀察者們
*/
@Override
public void notifyObserver(String newspaperName) {
observerList.forEach((b) -> b.update(newspaperName));
}
}
這裡是具體的觀察者,也就是被通知的物件
/**
* 觀察者A
*/
public class CustomerA implements Observer{
private Subject subject;
public CustomerA(Subject subject) {
this.subject = subject;
subject.registerObserver(this);
}
@Override
public void update(String newspaperName) {
System.out.println("CustomerA:《" + newspaperName + "》釋出了");
}
}
/**
* 觀察者B
*/
public class CustomerB implements Observer {
private Subject subject;
public CustomerB(Subject subject) {
this.subject = subject;
subject.registerObserver(this);
}
@Override
public void update(String newspaperName) {
System.out.println("CustomerB:《" + newspaperName + "》釋出了");
}
}
測試上面寫的簡易觀察者模式實現
public class ObserverTest {
public static void main(String[] args) {
Subject subject = new NewspaperOffice();
new CustomerA(subject);
// 註冊觀察者B
new CustomerB(subject);
// 通知觀察者們
subject.notifyObserver("日報A");
System.out.println("========================================");
subject.notifyObserver("日報B");
}
}
測試結果
總結
從上面的例子分析,主題和觀察則都是介面,主題通過介面通知依賴它的所有觀察者做某個操作(廣播通訊),只要知道具體物件的列表,而不需要知道某個具體的物件,上面例子NewspaperOffice只需擁有Observer陣列,至於具體的某個Observer並不關注,降低了物件之間的耦合度,這裡也是設計原則"針對介面程式設計,不針對實現程式設計"的體現。