一、定義與組成部分
- 定義
觀察者(Observer)模式 又名發佈-訂閱(Publish/Subscribe)模式。GOF 給觀察者模式如下定義:
一、定義與組成部分 -
定義
-
觀察者(Observer)模式 又名發佈-訂閱(Publish/Subscribe)模式。GOF 給觀察者模式如下定義:
-
定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。
面向對象設計的一個重要原則——單一職責原則。系統的每個對象應該將重點放在問題域中的離散抽象上。因此理想的情況下,一個對象只做一件事情。這樣在開發中也就帶來了諸多的好處:提供了重用性和維護性,也是進行重構的良好的基礎。 -
組成部分
觀察者模式由以下幾部分組成:
抽象目標角色(Subject):目標角色知道它的觀察者,可以有任意多個觀察者觀察同一個目標。並且提供註冊和刪除觀察者對象的接口。目標角色往往由抽象類或者接口來實現。
抽象觀察者角色(Observer):爲那些在目標發生改變時需要獲得通知的對象定義一個更新接口。抽象觀察者角色主要由抽象類或者接口來實現。
具體目標角色(Concrete Subject):將有關狀態存入各個Concrete Observer 對象。當它的狀態發生改變時, 向它的各個觀察者發出通知。
具體觀察者角色(Concrete Observer):存儲有關狀態,這些狀態應與目標的狀態保持一致。實現Observer 的更新接口以使自身狀態與目標的狀態保持一致。在本角色內也可以維護一個指向Concrete Subject 對象的引用。
使用觀察者模式的類圖,這樣能將關係清晰的表達出來。
在 Subject 這個抽象類中,提供了上面提到的功能,而且存在一個通知方法:notify。
還可以看到Subject 和ConcreteSubject 之間可以說是使用了模板模式(這個模式真是簡單普遍到一不小心就用到了)。
這樣當具體目標角色的狀態發生改變,按照約定則會去調用通知方法,在這個方法中則會根據目標角色中註冊的觀察者名單來逐個調用相應的update 方法來調整觀察者的狀態。
這樣觀察者模式就走完了一個流程。
二、實現觀察者模式
MySubject類就是我們的主對象,Observer1和Observer2是依賴於MySubject的對象,當MySubject變化時,Observer1和Observer2必然變化。
AbstractSubject類中定義着需要監控的對象列表,可以對其進行修改:增加或刪除被監控對象,且當MySubject變化時,負責通知在列表內存在的對象。
Observer接口:
public interface Observer {
public void update();
}
實現類:Observer1
public class Observer1 implements Observer {br/>@Override
public void update() {
System.out.println("observer1 接收到了!");
}
}
實現類:Observer2
public class Observer2 implements Observer{br/>@Override
public void update() {
System.out.println("observer2 接收到了!");
}
}
Subject接口
public interface Subject {/**
- 增加觀察者
- @param observer
*/
public void add(Observer observer);
/**
- 刪除觀察者
- @param observer
*/
public void del(Observer observer);
/**
- 通知所有的觀察者
*/
public void notifyObservers();
/**
- 自身的操作
*/
public void operation();
}
Subject實現類
public abstract class AbstractSubject implements Subject {
private Vector<Observer> vector = new Vector<Observer>();
@Override
public void add(Observer observer) {
vector.add(observer);
}@Override
public void del(Observer observer) {
vector.remove(observer);
}@Override
public void notifyObservers() {
Enumeration<Observer> enumo = vector.elements();
while (enumo.hasMoreElements()) {
enumo.nextElement().update();
}
}@Override
public void operation() {