觀察者模式定義對象的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都會得到通知並被自動更新。
一個簡單的例子是,在星際爭霸的蟲族中有一個初級單位叫做跳狗(Zergling),玩家可以在研究中心爲它升級“腎上腺素”,升級之後,跳狗的攻擊速度會翻倍。在這個模型中,我們可以看出,所有的跳狗都依賴於研究中心,當研究中心研究出腎上腺素後,通知每一個跳狗單位,它們被迫進行自我更新——升級速度加倍。在觀察者模型中,我們稱研究中心爲目標(Subject),而跳狗爲觀察者(Observer)。觀察者觀察目標的變化,如果目標發生了變化,那麼觀察者自身也會跟着變化。
以下是Java代碼:
import java.util.ArrayList;
abstract class Subject{
ArrayList<Observer> observers = new ArrayList<Observer>();
public void attach(Observer observer){
if (!observers.contains(observer))
observers.add(observer);
}
public void detach(Observer observer){
if (observers.contains(observer))
observers.remove(observer);
}
protected void notifyObservers(){
for (Observer o : observers){
o.update(this);
}
}
}
abstract class Observer{
Subject subject;
public Observer(Subject subject){
this.subject = subject;
subject.attach(this);
}
abstract void update(Subject subject);
}
class AdrenalUpgrade extends Subject{
public void upgrade(){
notifyObservers();
}
}
class Zergling extends Observer {
public Zergling(Subject subject) {
super(subject);
}
public void update(Subject subject) {
if (subject == this.subject){
System.out.println("Zergling的腎上腺素被刺激,攻擊速度翻倍!");
}
}
}
public class ObserverExample
{
public static void main(String[] args) {
AdrenalUpgrade adrenalUpgrade = new AdrenalUpgrade();
Zergling z1 = new Zergling(adrenalUpgrade);
Zergling z2 = new Zergling(adrenalUpgrade);
Zergling z3 = new Zergling(adrenalUpgrade);
Zergling z4 = new Zergling(adrenalUpgrade);
Zergling z5 = new Zergling(adrenalUpgrade);
Zergling z6 = new Zergling(adrenalUpgrade);
Zergling z7 = new Zergling(adrenalUpgrade);
adrenalUpgrade.upgrade();
}
}
Subject的是目標的基類,它可以attach或detach一個Observer。Subject含有一個List用於記錄自己被哪些Observer依賴,當自身的狀態改變時,會依次調用每一個Observer的update()方法。例如在main方法中,我們分別建立了z1、z2……z7共7個Zergling單位,它們都attach到了AdrenalUpgrade上,當AdrenalUpgrade調用了upgrade()時,會給每一個Zergling發出通知,因此程序的運行結果爲:
Zergling的腎上腺素被刺激,攻擊速度翻倍!
Zergling的腎上腺素被刺激,攻擊速度翻倍!
Zergling的腎上腺素被刺激,攻擊速度翻倍!
Zergling的腎上腺素被刺激,攻擊速度翻倍!
Zergling的腎上腺素被刺激,攻擊速度翻倍!
Zergling的腎上腺素被刺激,攻擊速度翻倍!
Zergling的腎上腺素被刺激,攻擊速度翻倍!
以上就是觀察者模式的一個例子。有興趣的同學可以看一看MVC(C#)結構,它可能是觀察者模式中最有名的結構之一了。