GoF本 Mediator

GoFデザインパターン勉強メモ

ねらい

  • オブジェクトの相互作用をカプセル化するためのオブジェクトを定義する
  • オブジェクトどうしを疎結合にする

モチベーション

  • システムをオブジェクトに細分すると再利用性が高まる
  • が、オブジェクトの相互作用が増加してくると、このメリットが再び失われる

    • 極論、すべてのオブジェクトが自分以外を知っているという状況

      • 【補】nC2 = n(n-1)/2 = O(n^2) のオーダー
    • オブジェクトが単体で成り立たなくなる
    • 依存ありきになると、結局一枚岩と変わらない
  • ふるまいのカスタマイズも難しくなる

    • ふるまいが多数のオブジェクトで定義される
    • 継承してoverrideすべきクラスも多岐にわたってしまう
  • mediatorオブジェクトをもうけ、総体的なふるまいをカプセル化することでこれらを回避できる

    • 各々のオブジェクトはmediatorを通して相互作用する

      • 【補】相互作用の本数はO(n)に減る

つかいどころ

  • オブジェクト同士が、よく定義された形で、しかし複雑に相互作用する

    • 【補】「よく定義された」というのは、「静的に決まっている」ということか
  • オブジェクトが多くのオブジェクトと相互作用するため、再利用が困難
  • システムのふるまいをカスタマイズする際に、たくさんのクラスを継承・overrideするのを避けたい

構造

stub

登場人物

  • Mediator

    • colleagueオブジェクトと相互作用するインターフェースの定義
  • ConcreteMediator

    • Mediatorの実装クラス
    • colleagueを保持・管理する
    • システムのふるまいをカスタマイズする際には、これだけ継承・overrideすればよい
  • Colleague

    • システムを構成するクラスのインタフェース
  • ConcreteColleague classes

    • システムを構成するオブジェクトのクラス
    • 帰属するmediatorオブジェクトを知っている
    • 他のcolleagueと直接は相互作用せず、mediatorを通して間接的に相互作用する

クライアントコードからの利用

  • colleagueオブジェクトはmediatorにリクエストを送ったり、から受け取ったりする
  • mediatorオブジェクトは、リクエストの交通整理を行い、適切なcolleagueオブジェクトにリクエストを送り、協調動作させる

結果

  • システムのふるまいをカスタマイズする際、クラスの継承の数を少なくすることができる

    • Mediatorだけ派生すればいい
  • colleagueオブジェクト間を疎結合にできる

    • ColleagueクラスやMediatorクラスを独立して再利用できる

      • Colleagueクラス群は当然疎結合になる
      • ColleagueMediatorともにインタフェースなら、これらも疎結合
  • オブジェクト間の関連がシンプルになる

    • 元々: 多対多
    • Mediator Pattern: 1対多 (Mediator vs Colleagues)
    • 【補】相互作用の本数もO(n^2)からO(n)になる
  • オブジェクトの協調動作に集中できるようになる

    • Mediatorの実装の中では、colleagueオブジェクト個々のふるまいは抽象化される(実装を見なくて済む)
  • 制御が中央集権的になる

    • 【補】Mediatorの複雑性はO(n)で増加する
    • 個々のColleagueよりは複雑
    • Mediator自体が一枚岩になってしまいかねない

実装にあたり考えるべきこと

  • Mediator抽象クラスを省く

    • colleagueオブジェクトたちが協調動作するmediatorオブジェクトが一種類だけなら不要
    • 疎結合ではなくなる
  • Colleague-Mediator間の相互作用

    • MediatorをObserverとしてObserverパターンを適用する

      • Colleagueクラス群はSubjectに相当
      • colleagueオブジェクトは状態が変化したら通知し、mediatorはこれを購読する
      • mediatorは他のcolleagueにこれを伝播する
    • Mediatorに、専用の通知インタフェースを定義する

      • colleagueは帰属するmediatorを知っている
      • colleagueは状態の変化をmediatorに通知するさい、colleague自身も引数として渡す
      • mediatorcolleagueオブジェクトをもってリクエストの送信元colleagueを特定する
      • あとはif-elseやらswitch-caseやらでリクエストの交通整理を行う

関連するパターン

  • Facade Patternとの対比
Facade Mediator
類似点 facadeオブジェクト mediatorオブジェクト
メッセージのやりとり Facade -> subsystem classes
単方向
Mediator <-> Colleague classes
双方向
ねらい システムを簡単に使うための窓口の提供。
facadeはなくてもシステムは動く
オブジェクトを協調動作させる。
mediatorは必要不可欠