回答:
オブザーバーとメディエーター、デザインパターン、再利用可能なオブジェクト指向ソフトウェアの要素という用語を生み出したオリジナルの本では、メディエーターパターンはオブザーバーパターンを使用して実装できると述べています。ただし、同僚(オブザーバーパターンのサブジェクトとほぼ同等)にMediatorクラスまたはMediatorインターフェイスへの参照を持たせることで実装することもできます。
オブザーバーパターンを使用したい場合は多くありますが、重要なのは、オブジェクト上で、他のオブジェクトがその状態を監視していることを知らないことです。
メディエーターはもう少し具体的です。クラスが直接通信するのではなく、メディエーターを介して通信することを避けます。これは、通信をそれを処理するだけのクラスにオフロードできるようにすることで、単一責任の原則に役立ちます。
古典的なMediatorの例はGUIです。単純なアプローチでは、「Fooパネルが無効で、Barパネルに「日付を入力してください」というラベルがある場合、サーバーを呼び出さないでください」 Mediatorパターンでは、「私はただのボタンであり、FooパネルとBarパネルのラベルについて何も知らないので、サーバーを呼び出すかどうかをメディエーターに尋ねる」と言うことができます。今は大丈夫です。」
または、オブザーバーパターンを使用して実装されている場合、ボタンは「ねえ、オブザーバー(メディエーターを含む)、私の状態が変更されました(誰かが私をクリックしました。)私の例ではおそらくあまり意味がありませんが、時には意味があり、ObserverとMediatorの違いは、コード自体の違いよりも意図の1つです。
オブザーバーパターンは、オブザーバー間の調整が不要で、オブザーブ関係が一方向に向いている場合にうまく機能します。
たとえば、オブジェクトBとCがオブジェクトAを監視するようにします。オブジェクトAがイベントXを発生させると、オブジェクトBはメソッドY()を実行し、オブジェクトCはメソッドZ()を実行します。メソッドBY()とCZ()が完全に独立しており、調整が不要な場合は、先に進み、オブザーバーパターンを使用します。
一方、CZ()の前にBY()を実行する必要がある場合、メディエーターがこの調整をカプセル化するメディエーターパターンを使用する必要があります。このシナリオでは、メディエーターMはオブジェクトAを観察し、オブジェクトBおよびCへの参照を持ちます。AがイベントXを起動すると、Mはイベントを処理し、規定の順序でBY()およびCZ()を呼び出します。
また、オブジェクトA、B、およびCがお互いを観察する必要がある場合、仲介者としてメディエーターを使用すると、これらのオブジェクトを分離し、スパゲッティコードを回避するのに大いに役立ちます。
このObserver
パターンは、あるクラス(監視対象クラス)で実行されるアクションが別のクラス(監視対象クラス)で反応を生成する必要がある場合に使用されますが、監視対象クラスを監視クラスに結合することは望ましくありません。これは非常に一般的なパターンです。SAX XMLパーサーが良い例かもしれません。SAXパーサーを使用するために、クライアントはContentHandler
インターフェイスを実装して、パーサー操作を「監視」します。パーサーは、XMLドキュメントの要素を検出すると、のメソッドを呼び出しますContentHandler
。パーサーはクライアントコードを呼び出すことができますが、パーサーはクライアントコードに結合されていません。
Mediator
パターンは、オブジェクトのセットの使用パターンのカプセル化です。クライアントコードは、複数の他のクラスに結合されるのではなく、メディエーターにのみ結合されます。カプセル化されたオブジェクトのライフタイムがメディエーターのライフタイムから独立していることを除いて、集約に似ています。
簡単に言えば(覚えておくために):
オブザーバー:あるオブジェクトに別のオブジェクトの状態変更を通知する場合に使用します(厳密には、イベントの使用はオブザーバーです)
メディエーターを理解するために、最初にFacadeを検討すると簡単です。Facadeは個別のクラス(サブシステム全体)の機能を集約し、その機能を単一のインターフェースで提供します。
メディエーター:Facadeと同じですが、すべての集約クラスの機能を組み合わせて新しい機能を生成します。(良い説明はこちら)