1. 程式人生 > >Java設計模式之從[星際爭霸的兵種升級]分析觀察者(Observer)模式

Java設計模式之從[星際爭霸的兵種升級]分析觀察者(Observer)模式

  觀察者模式定義物件的一種一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴於它的物件都會得到通知並被自動更新。

  一個簡單的例子是,在星際爭霸的蟲族中有一個初級單位叫做跳狗(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#)結構,它可能是觀察者模式中最有名的結構之一了。