関連クラスの適用

相互参照している 2 つのクラスがある。これらの関連を疎にしたい。そのような場合には、互いの関係に注目した関連クラスを中間に作成することによって、結合を弱くすることができる。UML で言うところの「社員」と「会社」が「雇用」の関係で表された図がそれなのだが、UML ではピンと来なかったので、身近なコードに置き換えてみる。

勇者 1000 人とモンスター 1000 匹が戦う「Heroes vs. Monsters」というストラテジーゲームがあるとする。このゲームの肝である戦闘を管理したい。しかし、勇者とモンスター間の攻撃は多対多となるために、クライアントは全ての勇者、又はモンスターのリストを総ざらいして、各戦闘を実行しなければならない。

そこで、勇者とモンスターの「敵対関係」に着目した Battle クラスを作成する。Battle という関連クラスが仲介することで、各キャラクタは自分の敵を管理する必要が無くなる。

勇者

class Hero {
/**
*  攻撃をする
*  @param target 攻撃対象
*/
public function attack(target:Monster):Void;
}

モンスター

class Monster {
/**
*  攻撃をする
*  @param target 攻撃対象
*/
public function attack(target:Hero):Void;
}

戦闘

class Battle {
private var hero:Hero;
private var monster:Monster;
public function getHero():Hero;
public function getMonster():Monster;
}

Battle クラスに攻撃の実装をしても良いが、コレクションクラス BattleList を作成し、クライアントは、このコレクションに対して操作を行う。

戦闘リスト

class BattleList {
private var battles:Array;
/**
*  戦闘を開始する
*/
public function openFire():Void {
for (var i:Number = 0; i < this.battles.length; i++) {
var battle:Battle = this.battles[i];
var hero:Hero = battle.getHero();
var monster:Monster = battle.getMonster();
//互いに攻撃する
hero.attack(monster);
monster.attack(hero);
}
}
}

openFire() メソッドを呼ぶことで、発生している全ての戦闘が開始される。