Observer 觀察者模式
觀察者模式:
觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。
這個主題對象在狀態發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。觀察者模式是一種對象行爲型模式。觀察者模式的別名包括:
發佈-訂閱(Publish/Subscribe)模式, 模型-視圖(Model/View)模式,
源-監聽器(Source/Listener)模式, 從屬者(Dependents)模式。結構圖:
示例類圖:
示例代碼:
public interface Subject {
public void add(Observer observer);
public void remove(Observer observer);
public void notifyObserver();
}
// ConcreteSubject
public class NumberSubject implements Subject {
private List<Observer> observers = new ArrayList<Observer>();
private int num;
@Override
public void add(Observer observer) {
if (!observers.contains(observer))
observers.add(observer);
}
@Override
public void remove(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObserver() {
for (Observer observer : observers) {
observer.update();
}
}
public void setNum(int num) {
this.num = num;
notifyObserver();// notifyObserver
}
public int getNum() {
return num;
}
}
public interface Observer {
public void update();
}
// ConcreteObserver
public class BinaryObserver implements Observer {
private NumberSubject subject;
public BinaryObserver(NumberSubject subject) {
this.subject = subject;
subject.add(this);
}
@Override
public void update() {
System.out.println("Binary:" + Integer.toBinaryString(subject.getNum()));
}
}
public class OctalObserver implements Observer {
private NumberSubject subject;
public OctalObserver(NumberSubject subject) {
this.subject = subject;
subject.add(this);
}
@Override
public void update() {
System.out.println("Octal:" + Integer.toOctalString(subject.getNum()));
}
}
public class HexObserver implements Observer {
private NumberSubject subject;
public HexObserver(NumberSubject subject) {
this.subject = subject;
subject.add(this);
}
@Override
public void update() {
System.out.println("Hex:" + Integer.toHexString(subject.getNum()).toUpperCase());
}
}
// 測試
public class ObserverTest {
public static void main(String[] args) {
NumberSubject subject = new NumberSubject();
new BinaryObserver(subject);
new OctalObserver(subject);
new HexObserver(subject);
subject.setNum(10);
subject.setNum(1024);
}
}
抽象主題(Subject):
它把所有觀察者對象的引用保存到一個聚集裏,每個主題都可以有任何數量的觀察者。
抽象主題提供一個接口,可以增加和刪除觀察者對象。具體主題(ConcreteSubject):
將有關狀態存入具體觀察者對象;在具體主題內部狀態改變時,給所有登記過的觀察者發出通知。抽象觀察者(Observer):
爲所有的具體觀察者定義一個接口,在得到主題通知時更新自己。
4.具體觀察者(ConcreteObserver):
實現抽象觀察者角色所要求的更新接口,以便使本身的狀態與主題狀態協調。
優點
觀察者模式解除了主題和具體觀察者的耦合,讓耦合的雙方都依賴於抽象,而不是依賴具體。從而使得各自的變化都不會影響另一邊的變化。缺點
依賴關係並未完全解除,抽象通知者依舊依賴抽象的觀察者。適用場景
- 當一個對象的改變需要給變其它對象時,而且它不知道具體有多少個對象有待改變時。
- 一個抽象某型有兩個方面,當其中一個方面依賴於另一個方面,這時用觀察者模式可以將這兩者封裝在獨立的對象中使它們各自獨立地改變和複用。