相互参照している 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() メソッドを呼ぶことで、発生している全ての戦闘が開始される。