Answers:
在最初创造了“观察者和中介者”,“ 设计模式”,“可重用的面向对象软件的元素”一词的原始书中,它说可以通过使用观察者模式来实现中介者模式。但是,也可以通过让同事(大致相当于观察者模式的主题)引用对Mediator类或Mediator接口的引用来实现。
在许多情况下,当您想使用观察者模式时,它们的关键是对象上不应该知道其他对象正在观察其状态。
调解器更为具体,它避免让类直接进行通信,而是通过调解器进行通信。通过允许将通信卸载到仅处理该类的类,这有助于单一职责原则。
一个经典的Mediator示例是在GUI中,其中,幼稚的方法可能会导致按钮单击事件中的代码显示为“如果Foo面板被禁用并且Bar面板上有一个标签为“ Please enter date”的标签,请不要调用服务器,否则,继续前进”,如果使用Mediator模式,它可能会说“我只是一个按钮,并且对Foo面板和Bar面板上的标签一无所知,所以我只想问问中介者是否呼叫服务器现在可以。”
或者,如果使用观察者模式实现该按钮,则该按钮将显示“嘿,观察者(其中包括调解人),我的状态发生了变化(有人单击了我。如果有需要,请对此做一些事情”)。在我的示例中,这可能没有什么意义,但有时却没有意义,并且Observer和Mediator之间的差异将是意图的其中之一,而不是代码本身的差异。
当观察者之间不需要协调并且观察关系为一种方式时,观察者模式会很好地工作。
例如,让对象B和C观察对象A。当对象A触发事件X时,对象B应该执行方法Y(),而对象C应该执行方法Z()。如果方法BY()和CZ()完全独立并且不需要协调,请继续使用观察者模式。
另一方面,如果BY()必须在CZ()之前执行,那么您将要使用调解器模式,其中调解器封装了此协调。在这种情况下,调解器M将观察对象A,并引用对象B和C。当A触发事件X时,M将处理该事件并按指定顺序调用BY()和CZ()。
同样,如果对象A,B和C需要彼此观察,则使用中介程序作为中介将有助于使这些对象分离并避免意大利面条式代码。
Observer
当对一个类别(观察到的类别)采取的行动需要在另一类别(观察到的类别)中产生反应时使用该模式,但是将观察到的类别与观察到的类别耦合是不可取的。这是非常常见的模式。SAX XML解析器可能是一个很好的例子。要使用SAX解析器,客户端将实现ContentHandler
接口以“观察”解析器操作。当解析器遇到XML文档的元素时,它将调用的方法ContentHandler
。解析器能够调用客户端代码,但是解析器未耦合到客户端代码。
该Mediator
模式是一组对象使用模式的封装。客户端代码仅耦合到中介程序,而不耦合到多个其他类。除了封装对象的生存期独立于中介程序的生存期外,它与聚合类似。
简单来说(我曾经记得):
观察者:当一个对象想要获知另一个对象的状态变化时使用(严格来说,使用事件是观察者)
为了理解调解器,当您首先考虑Facade时,我会发现它更容易:Facade聚合单独类的功能(有时是整个子系统),并在单个界面中提供该功能。
介体:与Facade相同,只是它结合了所有聚合类的功能以产生新功能。(在这里很好的解释)