88

我一直在研究这两种模式之间的区别。

我知道外观封装了对子系统的访问,而中介封装了组件之间的交互。

我知道子系统组件不知道外观,而组件显然知道中介。

我目前正在使用外观来封装检索配置信息的方法,例如 App.Config、存储在 SQL 中的用户设置、程序集信息等,以及用于在不同窗体之间导航的中介。

然而,大多数网站都指出中介“增加了功能”。他们这是什么意思?中介如何添加功能?

4

8 回答 8

107

...大多数网站指出中介“增加了功能”...

外观仅从不同的角度公开现有功能。

中介“添加”功能,因为它结合了不同的现有功能来创建新功能。

举个例子:

你有一个日志系统。从该日志系统,您可以将日志记录到文件、套接字或数据库。

使用外观设计模式,您可以将现有功能的所有关系“隐藏”在外观暴露的单个“界面”后面。

客户端代码:

 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 是具有“调试”方法的包私有对象。这样,Facade 并没有添加功能,它只是委托给一些现有的对象。

另一方面,中介通过组合不同的对象来添加新的功能。

相同的客户端代码:

 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();
               }
      }
 }

在此代码中,中介是包含创建适当“通道”以记录日志并将日志放入该通道的业务逻辑的那个。中介正在“创建”功能。

当然,使用多态性有更好的方法来实现这一点,但这里的重点是展示中介如何通过组合现有功能“添加”新功能(在我的示例中没有表现出非常抱歉)但想象一下中介,阅读从数据库中记录远程主机的位置,然后创建一个客户端,最后将日志消息写入该客户端打印流。这样,调解员将在不同对象之间“调解”。

最后,外观是一种结构模式,即描述对象的组成,而中介是一种行为模式,即描述对象交互的方式。

我希望这有帮助。

于 2009-01-27T04:53:07.703 回答
13

我正在使用调解器来添加日志文件功能。

它是这样工作的:

  • Obj A 告诉中介它需要做一些事情。
  • 中介将消息发送到各种客户端对象。
  • Obj B 做 Obj A 需要的事情,并通过中介发回适当的消息。
  • 同时,Obj C 也由中介发送这两条消息,并记录结果。这样,我们可以从日志文件中获取用户统计信息。
  • Obj D 也可以是错误检查器,因此如果 Obj B 响应 Obj A 的请求是不可能的,则 Obj D 可能是向用户报告的东西。错误现在可以记录在与常规活动不同的文件中,并且可以使用其他一些方式来表现 Obj A 不应该真正关心的行为(哔哔声等)。
于 2009-01-27T01:03:33.440 回答
12

在相关模式下,gof说: Facade (185) 与 Mediator 的不同之处在于它抽象了对象子系统以提供更方便的接口。它的协议是单向的;也就是说,Facade 对象向子系统类发出请求,反之则不然。相比之下,Mediator 实现了同事对象不提供或不能提供的协作行为,并且协议是多向的。

于 2015-06-13T07:25:21.870 回答
10
于 2013-05-31T00:38:59.220 回答
4

我认为区别是有方向的:Facade 是客户端和 Facade 之间的一种单向通信;mediator 可以是双向对话,消息在客户端和 mediator 之间来回流动。

于 2009-01-27T02:07:38.537 回答
3

在“设计模式”一书中,中介者模式的关键描述如下:“它(中介者)充当小部件(即,'一组'相互依赖的对象)的通信中心。”

换句话说,中介对象是唯一的超对象,它知道一组协作对象中的所有其他对象以及它们应该如何相互交互。所有其他对象都应该与中介对象交互,而不是彼此交互。

相反,外观是子系统中一组接口的“统一接口”——供子系统的消费者使用——而不是子系统的组件。

于 2011-01-12T04:09:19.077 回答
2

您可以在这个 SE 问题中找到有关外观模式的详细信息:

什么是外观设计模式?

Facade为复杂系统提供简单统一的接口。

这篇文章中提供了真实世界的示例(cleartrip 航班+酒店预订):

什么是外观设计模式?

中介者模式:定义一个对象,封装一组对象如何交互。Mediator 通过阻止对象显式地相互引用来促进松散耦合,并且它允许您独立地改变它们的交互。

下面的 SE 问题中提供了 Mesh 网络拓扑的真实示例:

中介者与观察者的面向对象设计模式

关于您对 Mediator 的查询增加了责任:

  1. Facade 仅提供与现有子系统的接口。现有的子系统不知道 Facade 类本身。

  2. 中介者知道同事对象。它使不同同事之间的沟通成为可能。在我在链接问题中引用的示例中,ConcreteMediator ( NetworkMediator ) 将一位同事的注册和注销事件的通知发送给所有其他同事。

于 2016-08-08T16:09:30.070 回答
0

两者都对另一组对象施加某种策略。Facade从上执行策略,Mediator从下执行策略。Facade的使用是可见的和约束的,而Mediator的使用是不可见的和启用的。

当您想为一组具有复杂和通用接口的对象提供简单和特定的接口时,使用外观模式。

The Mediator pattern also imposes policy. However, whereas Facade imposed its policy in a visible and constraining way, Mediator imposes its policies in a hidden and unconstrained way.

Agile Software Development, Principles, Patterns, and Practices Robert C. Martin.

于 2018-05-16T12:07:13.040 回答