ファサードvs.メディエーター


83

私はこれら2つのパターンの違いを研究してきました。

ファサードはサブシステムへのアクセスをカプセル化し、メディエーターはコンポーネント間の相互作用をカプセル化することを理解しています。

サブシステムコンポーネントはファサードを認識していませんが、コンポーネントは明らかにメディエーターを認識していることを理解しています。

現在、App.Config、SQLに格納されているユーザー設定、アセンブリ情報などの構成情報を取得する方法をカプセル化するためのファサードと、異なるWindowsフォーム間のナビゲーション用のメディエーターを使用しています。

ただし、ほとんどのサイトは、メディエーターが「機能を追加する」と指摘しています。これはどういう意味ですか?メディエーターはどのように機能を追加しますか?

回答:


103

...ほとんどのサイトは、メディエーターが「機能を追加する」と指摘しています...

ファサードは、唯一異なる視点からの既存の機能を公開します。

メディエータは、それが新しいものを作成するために、別の既存の機能を兼ね備えているので機能「を追加します」。

次の例を見てください。

ロギングシステムがあります。そのログシステムから、ファイル、ソケット、またはデータベースのいずれかにログを記録できます。

ファサードデザインパターンを使用すると、ファサードが公開する単一の「インターフェイス」の背後にある既存の機能からすべての関係を「隠す」ことができます。

クライアントコード:

 Logger logger = new Logger();
 logger.initLogger("someLogger");
 logger.debug("message");

実装には、多くのオブジェクトの相互作用が含まれる場合があります。しかし、最後に、機能はすでに存在します。おそらく、「デバッグ」メソッドは次のように実装されます。

実装:

 class Logger { 

      private LoggerImpl internalLogger;
      private LoggerManager manager;

      public void initLogger( String loggerName ) {
          this.internalLogger = manager.getLogger( loggerName ); 
      }

      public void debug( String message ) { 
          this.internalLogger.debug( message );
      }     
 }

機能はすでに存在します。ファサードはそれを隠すだけです。この架空のケースでは、LoggerManagerが正しいロガーの作成を処理し、LoggerImplは「debug」メソッドを持つパッケージプライベートオブジェクトです。このように、ファサードは機能を追加せず、既存のオブジェクトに委任するだけです。

一方、メディエーターは、さまざまなオブジェクトを組み合わせることで新しい機能を追加します。

同じクライアントコード:

 Logger logger = new Logger();
 logger.initLogger("someLogger");
 logger.debug("message");

実装:

 class Logger { 

      private java.io.PrintStream out;
      private java.net.Socket client;
      private java.sql.Connection dbConnection;
      private String loggerName;


      public void initLogger( String loggerName ) {
               this.loggerName = loggerName;
               if ( loggerName == "someLogger" ) { 
                    out = new PrintStream( new File("app.log"));
               } else if ( loggerName == "serverLog" ) { 
                    client = new Socket("127.0.0.1", 1234 );
               } else if( loggerName == "dblog") { 
                    dbConnection = Class.forName()... .
               }

      }

      public void debug( String message ) { 

               if ( loggerName == "someLogger" ) { 
                    out.println( message );
               } else if ( loggerName == "serverLog" ) { 
                    ObjectOutputStrewam oos = 
                           new ObjectOutputStrewam( client.getOutputStream());
                    oos.writeObject( message );
               } else if( loggerName == "dblog") { 
                    Pstmt pstmt = dbConnection.prepareStatment( LOG_SQL );
                    pstmt.setParameter(1, message );
                    pstmt.executeUpdate();
                    dbConnection.commit();
               }
      }
 }

このコードでは、メディエーターは、ログに記録する適切な「チャネル」を作成し、そのチャネルにログを作成するためのビジネスロジックを含むものです。メディエーターは機能を「作成」しています。

もちろん、ポリモーフィズムを使用してこれを実装するより良い方法がありますが、ここでのポイントは、メディエーターが既存の機能を組み合わせることによって新しい機能を「追加」する方法を示すことです(私のサンプルではあまり申し訳ありませんでした)が、メディエーターを想像してください、読んでくださいデータベースから、ログを記録するリモートホスト、次にクライアントを作成し、最後にそのクライアントにログメッセージを印刷ストリームに書き込みます。このようにして、メディエーターは異なるオブジェクト間を「仲介」します。

最後に、ファサードは構造パターンです。つまり、オブジェクトの構成を記述し、メディエーターは動作を記述します。つまり、オブジェクトが相互作用する方法を記述します。

これがお役に立てば幸いです。


素晴らしい説明..これに関連する質問があります。ReentrantLockとAbstractQueueSynchronizer(AQS)の構成方法は、ファサードパターンの例に当てはまりますか?つまり、ReentrantLockは、サブシステムとして内部に存在するAQSの機能のみを公開します。
AKS

@RayTayekの答えはあなたの答えと矛盾しますか?あなたのメディエーターのプロトコルは一方向ですよね?
ナレク2015年

メディエーターが新しい機能を追加することを示すサイト(ウィキペディアを含む)は見つかりませんでした。いくつかの参考文献を指摘できますか?
開発者

ここの@developerはリファレンスです。下部を見てください。
Dario Fumagalli 2018年

13

メディエーターを使用してログファイル機能を追加しています。

それはこのように動作します:

  • Obj Aは、メディエーターに何かをする必要があることを伝えます。
  • メディエーターは、さまざまなクライアントオブジェクトにメッセージを送信します。
  • Obj Bは、Obj Aが必要とすることを実行し、メディエーターを介して適切なメッセージを送り返します。
  • 一方、Obj Cもメディエーターから両方のメッセージを送信され、結果をログに記録します。このようにして、ログファイルからユーザー統計を取得できます。
  • Obj Dもエラーチェッカーである可能性があるため、ObjBがObjAの要求が不可能であると応答した場合、ObjDはそれをユーザーに報告するものである可能性があります。エラーは通常のアクティビティとは異なるファイルに記録できるようになり、Obj Aが実際には気にしないはずの動作(ビープ音など)を行うために他の手段を使用できるようになりました。

11

関連するパターンの下で、gofは次のように述べています。Facade(185)は、オブジェクトのサブシステムを抽象化してより便利なインターフェイスを提供するという点でMediatorとは異なります。そのプロトコルは単方向です。つまり、Facadeオブジェクトはサブシステムクラスの要求を行いますが、その逆は行いません。対照的に、Mediatorは、同僚のオブジェクトが提供しない、または提供できない協調動作を可能にし、プロトコルは多方向です。


7

簡単な例えを考えてみましょう。

ファサード:駐車場のように、電話すると

parkingLot.Out(car1);

mab be a simple chain works:

{
  car1.StartEngin();      
  attendant.charge();
  car1.driverOut();
}

メディエーター:信号機のように。

光と車の間には相互作用があります、

車はその状態によって制御されます。

多分これは「機能を追加する」メディエーターです


そして定義について:

ファサードのタイプ:構造

メディエーターのタイプ:行動

コンポーネントをより懸念するファサードは、統合されたインターフェイスに含まれてました 。

メディエーターは、オブジェクトのセットが どのように相互作用するかを懸念します


4

区別は方向性があると思いました。ファサードはクライアントとファサードの間の一方向の通信です。メディエーターは、クライアントとメディエーターの間でメッセージが行き来する双方向の会話にすることができます。


申し訳ありませんが、その違いは実際には間違っています。mmrの答えは正しいです。私が最初にそれらを見たときもあなたと同じことを信じていましたが
ロバートグールド

3

「DesignPatterns」の本から、メディエーターパターンのKEYは次のように説明されています:「それ(メディエーター)はウィジェット(つまり、相互に依存するオブジェクトの「a」グループ)の通信のハブとして機能します。」

言い換えると、メディエーターオブジェクトは、コラボレーションオブジェクトのグループ内の他のすべてのオブジェクトと、それらが互いにどのように相互作用するかを知っている唯一のスーパーオブジェクトです。他のすべてのオブジェクトは、相互にではなく、メディエーターオブジェクトと相互作用する必要があります。

対照的に、ファサードは、サブシステムのコンポーネント間ではなく、サブシステムのコンシューマーが使用するサブシステム内の一連のインターフェイスの「統合インターフェイス」です。


1

このSEの質問でファサードパターンの詳細を見つけることができます:

ファサードデザインパターンとは何ですか?

Facade 複雑なシステムへのシンプルで統一されたインターフェースを提供します。

実際の例(cleartripフライト+ホテル予約)は、この投稿で入手できます:

ファサードデザインパターンとは何ですか?

メディエーターパターン:オブジェクトのセットがどのように相互作用するかをカプセル化するオブジェクトを定義します。メディエーターは、オブジェクトが相互に明示的に参照しないようにすることで疎結合を促進し、オブジェクトの相互作用を個別に変更できるようにします。

メッシュネットワークトポロジの実際の例は、以下のSEの質問で提供されています。

メディエーターとオブザーバーのオブジェクト指向設計パターン

Mediatorでのクエリに関して、責任が追加されます。

  1. ファサードは、既存のサブシステムへのインターフェースのみを提供します。既存のサブシステムは、Facadeクラス自体を認識していません。

  2. メディエーターは同僚のオブジェクトについて知っています。異なる同僚間のコミュニケーションを可能にします。リンクされた質問で引用した例では、ConcreteMediatorNetworkMediator)は、ある同僚の登録および登録解除イベントの通知を他のすべての同僚に送信します。


1

どちらも、別のオブジェクトグループに何らかのポリシーを課します。ファサードは上からポリシーを課し、メディエーターは下からポリシーを課します。ファサードの使用は目に見えて制約がありますが、メディエーターの使用は目に見えず有効になっています。

ファサードあなたは複雑で、一般的なインターフェースを持つオブジェクトのグループに簡単で、特定のインターフェイスを提供する場合のパターンが使用されています。

メディエータのパターンは、ポリシーを課しています。ただし、Facadeがそのポリシーを目に見える制約のある方法で課したのに対し、Mediatorはそのポリシーを隠された制約のない方法で課します。

アジャイルソフトウェア開発、原則、パターン、および実践ロバートC.マーチン。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.