オブジェクトの協調動作について落ち着いて考えてみた。

プログラムで制御する装置はいくつもの機能から成っている。
例として次のような3つの機能から成る装置を制御するソフトウェアについて考えてみる。

  1. 電圧を出力する機能
  2. センサの感度を切り替える機能
  3. 状態を一定に保つ(フィードバック)

装置は測定部分に電圧をかけ、流れる電流をセンサで検出し、電流が一定になるように電圧をフィードバック制御する。ユーザーは、電圧、設定電流、センサの感度を自由に変更できる。
この装置をモデリングすると、まずそれぞれの機能を個別のオブジェクトに割り当てる。

  1. 電圧制御オブジェクト
  2. センサ制御オブジェクト
  3. フィードバック制御オブジェクト

これはまあ自然だろう。
装置が正しく動作するには各機能が正しく協調して動作する必要があるので、対応するオブジェクト同士も正しく協調しなくてはならない。例えば、ユーザーがセンサ感度を10倍に変更したとき、フィードバックの参照値も10倍にしなければならない。さもないと、本来の設定電流の1/10の電流でフィードバックが安定してしまう。こういう場合、イベントの流れは

(ユーザー) -> (GUI) -> (電圧オブジェクト) -> (フィードバックオブジェクト)

のようになる。ここではフィードバックオブジェクトの状態が電圧オブジェクトの状態に依存している。言い替えると、電圧オブジェクトは自分のパラメータが変更されたことをフィードバックオブジェクトに伝えることを知っていなければならない。このような依存性が増えてゆくと変更メッセージを送るべき相手がどんどん増えてゆき、メッセージを送った相手が自らを変更し、さらに変更メッセージを送り返すとメッセージの無限ループが起こってしまう。さらに、あるパラメータの変化に対する挙動を動的に変更する必要がでてきたりすると手に負えなくなる。
このような場合、Mediatorパターンを使って

(ユーザー) -> (GUI) -> (電圧オブジェクト) -> (Mediator) -> (フィードバックオブジェクト)

とすることで自分の変化をどのオブジェクトに複雑さをMediatorにカプセル化することができる。ユーザーからの変更を受けたオブジェクトはMediatorに変更メッセージを送るだけでよく、あとはMediatorが他のオブジェクトに連絡してくれる。また、オブジェクト同士の協調ルールを変更するにはMediatorを交換するだけでよい。(つまりStrategyパターン。)