May 07, 2003

Warcraft3でデザインパターン: Observer

[ Java ]
第三回目。今回は Observer。Footman がダメージを受けるたびに Paladin がそれを観察し、残り HP が少なくなったら Holy Light で回復させるという流れを Observer パターンで実現してみる。

Observer パターンで言うところの Observer としてインターフェース Hero を記述。Hero は Unit がダメージを受けると notify によってそれを知る。
package observer;

public interface Hero {
    public abstract void notify(Unit s);
}
一方、観察される側(Subject)として Unit クラス。(抽象クラス) 状態変化を知らせる相手をプールに登録/削除するメソッドとして addHero(), deleteHero() を用意する。加えて、サブクラスが使用する notifyHeros() を実装する。notifyHeros()  の中では Hero#notify() を使用して、Hero に状態変化を知らせる。
package observer;

import java.util.*;

/* Subject */
abstract public class Unit {
    private Vector heros = new Vector();

    public void addHero(Hero h) {
        heros.add(h);
    }

    public void deleteHero(Hero h) {
        heros.remove(h);
    }

    public void notifyHeros() {
        Iterator it = heros.iterator();

        while (it.hasNext()) {
            Hero h = (Hero) it.next();
            h.notify(this);
        }
    }

    public abstract void recoverHitPoint(int hp);
    public abstract int getHitPoint();
    public abstract void damage(int dam);
}
Hero インターフェースを実装するクラス、ConcreteObserver として Paladin クラス。Paladin は Unit から状態変化の知らせ(notify())があると、HPを調べて少なかったら Holy Light で HP を回復させる。
package observer;

/* Concrete Observer */
public class Paladin implements Hero {
    public void notify(Unit u) {
        // HPが100を切ったらHoly Lightで回復させよう
        if (u.getHitPoint() < 100) {
            holyLight(u);
        }
    }

    public void holyLight(Unit u) {
        System.out.println("Paladin: Holy Light!");
        u.recoverHitPoint(300);
    }
}
Unit クラスの実装クラス、ConcreteSubject として Footman。Footman はダメージを受けるたびに、自身が知っている Hero に対してそれを通知する。
package observer;

public class Footman extends Unit {
    private int hp = 420;

    public int getHitPoint() {
        return hp;
    }

    public void damage(int dam) {
        hp -= dam;

        System.out.println("Footman: 被" + dam + "ダメージ(" + hp + ")");

        // ダメージを受けたらHeroに知らせる
        notifyHeros();
    }

    // HP回復
    public void recoverHitPoint(int hp) {
        this.hp += hp;

        System.out.println("Footman: HP回復(" + this.hp + ")");
    }
}
以上で役者は揃ったので、クライアントとして Main クラスを用意する。Footman と Paladin のインスタンスを生成して、Footman に適当にダメージを与えてみる。
package observer;

public class Main {
    public static void main(String[] args) {
        Hero h = new Paladin();

        Unit u = new Footman();
        u.addHero(h);

        u.damage(400);
        u.damage(100);
        u.damage(50);
        u.damage(20);
        u.damage(100);
    }
}
実行結果は以下。Footman の状態変化に合わせて適時 Paladin が Holy Light で HP を回復させている。
Footman: 被400ダメージ(20)
Paladin: Holy Light!
Footman: HP回復(320)
Footman: 被100ダメージ(220)
Footman: 被50ダメージ(170)
Footman: 被20ダメージ(150)
Footman: 被100ダメージ(50)
Paladin: Holy Light!
Footman: HP回復(350)
Posted by naoya at May 7, 2003 01:00 AM | トラックバック (0)  b_entry.gif
トラックバック [0件]
TrackBack URL: http://mt.bloghackers.net/mt/suck-tbspams.cgi/65
コメント [0件]