定義了對象之間的一對多依賴,當一個對象改變狀態時,它的所有依賴者都會收到通知並自動更新。主題(Subject)是被觀察的對象,而其所有依賴者(Observer)稱為觀察者。 ...
模式定義
定義了對象之間的一對多依賴,當一個對象改變狀態時,它的所有依賴者都會收到通知並自動更新。主題(Subject)是被觀察的對象,而其所有依賴者(Observer)稱為觀察者。
設計原則
為交互對象之間的松耦合設計而努力:當兩個對象之間松耦合,它們依然可以交互,但是不清楚彼此的細節。由於松耦合的兩個對象之間互相依賴程度很低,因此系統具有彈性,能夠應對變化。
UML類圖
觀察者模式實例
定義被觀察者介面
package com.wpx.observer;
/**
* 抽象被觀察者介面
* 定義了添加、刪除、通知觀察者方法
*/
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
定義觀察者介面
package com.wpx.observer;
/**
* 抽象觀察者介面
* 定義了一個update()方法,當被觀察者調用notifyObservers()方法時,觀察者的update()方法會被回調
*/
public interface Observer {
public void update(String message);
}
定義被觀察者,實現Subject介面,對Subject介面的三個方法進行了具體實現,同時有一個List集合,用以保存註冊的觀察者,等需要通知觀察者時,遍歷該集合。
package com.wpx.observer;
import java.util.ArrayList;
import java.util.List;
/**
* 具體的被觀察者
*/
public class ConcreteSubject implements Subject {
private List<Observer> list;
private String message;
public ConcreteSubject() {
list = new ArrayList<Observer>();
}
@Override
public void registerObserver(Observer o) {
list.add(o);
}
@Override
public void removeObserver(Observer o) {
if (!list.isEmpty())
list.remove(o);
}
@Override
public void notifyObservers() {
for (int i = 0; i < list.size(); i++) {
Observer observer = list.get(i);
observer.update(message);
}
}
public void send(String s) {
this.message = s;
System.out.println("更新消息:" + s);
//消息更新,通知所有觀察者
notifyObservers();
}
}
定義觀察者,實現Observer介面,對方法進行實現
package com.wpx.observer;
/**
* 具體的觀察者
*/
public class ConcreteObserver implements Observer {
private String name;
private String message;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
this.message = message;
read();
}
public void read() {
System.out.println(name + " 收到消息:" + message);
}
}
測試觀察者模式,先創建一個被觀察者對象(公司),再創建三個觀察者對象(職工),公司先發佈消息說今天加班,張三一聽,不幹了辭職,之後公司又發佈消息明天放假,張三已經辭職,因此收不到消息,其他觀察者(職工)可以收到消息。
package com.wpx.observer;
/**
* 測試觀察者模式
*/
public class ObserverDemo {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer observer1 = new ConcreteObserver("張三");
Observer observer2 = new ConcreteObserver("李四");
Observer observer3 = new ConcreteObserver("王五");
subject.registerObserver(observer1);
subject.registerObserver(observer2);
subject.registerObserver(observer3);
subject.send("今天加班");
subject.removeObserver(observer1);
subject.send("明天放假");
}
}
運行結果
更新消息:今天加班
張三 收到消息:今天加班
李四 收到消息:今天加班
王五 收到消息:今天加班
更新消息:明天放假
李四 收到消息:明天放假
王五 收到消息:明天放假
Process finished with exit code 0
總結
- 觀察者模式是松偶合的。改變主題或觀察者中的一方,另一方不會受到影響。
- JDK中也有自帶的觀察者模式,但是被觀察者是一個類而不是介面,限制了它的使用和復用能力。JDK內置觀察者模式java.util.Observer介面, java.util.Observable類。
- 在JavaBean和Swing中也有觀察者模式的設計思想。