外立面与调解员


83

我一直在研究这两种模式之间的差异。

我知道,facade封装了对子系统的访问,而mediator封装了组件之间的交互。

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

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

但是,大多数站点都指出中介程序是“添加功能”。这是什么意思?调解员如何添加功能?

Answers:


103

...大多数网站都指出调解员“添加了功能” ...

外观仅暴露出从不同的角度的现有功能。

调解员“增加了”功能,因为它结合了不同的现有功能来创建一个新的。

请看以下示例:

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

使用立面设计模式,您可以将现有功能中的所有关系“隐藏”在立面公开的单个“接口”后面。

客户代码:

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

该实现可能涉及许多对象的交互。但是最后,该功能已经存在。“ debug”方法可能实现如下:

实现方式:

 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”方法的程序包专用对象。这样,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();
               }
      }
 }

在此代码中,调解器是一个包含业务逻辑的调解器,该逻辑创建一个适当的“通道”进行记录,并使该日志进入该通道。中介正在“创建”功能。

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

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

我希望这有帮助。


很好的解释..我有一个与此相关的问题。ReentrantLock和AbstractQueueSynchronizer(AQS)的组合方式是否适合Facade模式的示例?我的意思是ReentrantLock仅公开作为子系统存在于其中的AQS的功能。
AKS 2013年

@RayTayek的答案与您的答案矛盾吗?调解员的协议是单向的,对吗?
Narek

我找不到任何站点(包括Wikipedia)声明调解员添加了新功能。你能指出一些参考吗?
开发人员

@developer这里是参考,请看底部。
Dario Fumagalli

13

我正在使用中介程序来添加日志文件功能。

它是这样的:

  • Obj A告诉调解员它需要做些事情。
  • 中介器将消息发送到各种客户端对象。
  • Obj B完成Obj A所需的操作,并通过调解器发送回适当的消息。
  • 同时,Obj C也由调解器发送这两个消息,并记录结果。这样,我们可以从日志文件中获取用户统计信息。
  • Obj D也可能是一个错误检查器,因此,如果Obj B响应认为Obj A的请求是不可能的,则Obj D可能会向用户报告该错误。现在可以将错误记录在与常规活动不同的文件中,并且可以使用其他一些方式来表现(蜂鸣声,诸如此类)Obj A不应真正关心的本身。

11

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


7

举个简单的比喻:

外立面:打电话时就像停车场

parkingLot.Out(car1);

mab是一个简单的链工程:

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

调解员:喜欢交通灯。

灯光和汽车之间存在相互作用,

汽车受其状态控制。

我虽然可能是中介者“添加功能”


关于定义:

外立面类型:结构

调解人类型:行为

门面比较关心的成分包含统一的界面

调解员和调解员关注一组对象 如何相互作用


4

我认为区别是定向的:Facade是客户端和Facade之间的单向通信;调解器可以是双向对话,消息在客户端和调解器之间来回流动。


抱歉,但是这种区别实际上是错误的,mmr的答案是正确的。尽管当我初次看到它们时,我也相信和您一样的话
罗伯特·古尔德

3

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

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

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


1

您可以在以下SE问题中找到有关Facade模式的详细信息:

什么是立面设计模式?

Facade 为复杂的系统提供了一个简单统一的界面。

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

什么是立面设计模式?

调解员模式:定义一个对象,该对象封装了一组对象之间的交互方式。介体通过防止对象之间显式地相互引用来促进松散耦合,并且它使您可以独立地更改其交互。

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

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

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

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

  2. 调解员了解同事的对象。它使不同同事之间可以进行通信。在链接问题中引用的示例中,ConcreteMediatorNetworkMediator)将一个同事的注册和注销事件通知发送给所有其他同事。


1

两者都对另一组对象施加某种策略。外立面从上方强加政策,并且 Mediator从下方强加策略。Facade的使用是可见的并且是受约束的,而Mediator的使用是不可见的并且是启用的。

门面时,要提供一个简单的和具体的接口,一组对象,有一个复杂的和通用的接口模式被使用。

调解模式还规定政策。但是,尽管Facade以可见且受限制的方式实施其政策,但Mediator以隐藏且不受限制的方式。

敏捷软件开发,原理,模式和实践Robert C. Martin。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.