Mediator Vs Observer面向对象的devise模式

我一直在读“ 四人帮” ,以解决我的一些问题,并遇到调解员模式。

我曾经在我的项目中使用Observer来制作一些GUI应用程序。 我有点困惑,因为我没有发现两者之间的巨大差异。 我浏览find差异,但找不到我的查询任何答案。

有人能帮我区分这两者吗?

Observer模式:定义对象之间的一对多依赖关系,以便当一个对象改变状态时,所有的依赖关系都会被自动通知和更新。

介体模式:定义一个封装一组对象如何交互的对象。 中介者通过保持对象明确地相互引用来促进松耦合,并且可以让你独立地改变他们的交互。

来源: dofactory

例:

观察者模式:类A,可以有零个或多个Otypes的观察者注册。 当A中的某些内容发生变化时,通知所有的观察者。

中介模式:你有一些X类实例(或者甚至可能有几种不同的types:X,Y和Z),他们希望相互通信(但是你不希望每个实例都有明确的引用其他的),所以你创build了一个中介类M.每个X的实例都有一个对M的共享实例的引用,通过它可以和X(或X,Y和Z)的其他实例进行通信。

在原创的Observer和Mediator, Design Patterns,Elements of Reusable Object-Oriented Software这两个术语中,它说Mediator模式可以通过使用观察者模式来实现。 然而,也可以通过让同事(大致相当于观察者模式的主题)具有对调解员类或调解员界面的引用来实现。

有很多情况下,你想要使用观察者模式,他们的关键是一个对象不应该知道其他对象正在观察它的状态。

调解员是一个更具体一点,它避免了类直接沟通,而是通过中介。 这有助于单一职责原则,允许通信被卸载到只处理通信的类。

一个典型的Mediator例子是在一个graphics用户界面(GUI)中,那种天真的方法可能导致一个button点击事件的代码,说“如果Foo面板被禁用,酒吧面板有一个标签说:”请inputdate“,那么不要叫服务器,否则继续“,在中介模式中,可以说”我只是一个button,没有任何地球上的业务知道Foo面板和酒吧面板上的标签,所以我会问我的调解员,如果调用服务器现在好了。“

或者,如果Mediator使用Observer模式实现,button会说“嗨,观察者(包括调解员),我的状态改变了(有人点了我)。 在我的例子中,直接引用中介的意义可能不那么明显,但在很多情况下,使用Observer模式来实现中介是有道理的,而Observer和Mediator之间的区别只是代码本身的差异而已。

观察

没有

  • 客户1 :嘿, 主题 ,你什么时候改变?

  • 客户2 :你什么时候改变主题 ? 我没有注意到!

  • Client3 :我知道主题已经改变。

2.与

  • 客户沉默。
  • 一段时间之后 …
  • 主题 :尊敬的客户 ,我已经改变!

中间人

没有

  • 客户1 :嗨, 出租车1 ,带我去哪里。
  • 客户2 :嗨, 出租车1 ,带我去哪里。
  • 客户1 :嗨, 出租车2 ,带我去哪里。
  • 客户2 :嗨, 出租车2 ,带我去哪里。

2.与

  • 客户1 :嗨出租车中心 ,请带我去出租车
  • 客户2 :嗨出租车中心 ,请带我去出租车

这些模式用于不同的情况:

当你有两个子系统有一些依赖关系,并且其中一个子系统是由于一个变化而使用的,因为你可能不想改变依赖于另一个系统的系统,所以你可能需要引入一个中介者解耦它们之间的依赖关系。 这样,当其中一个子系统发生变化时,您只需更新中介。

观察者模式用于当一个类想要允许其他类注册自己并接收事件通知,例如ButtonListener等。

这两种模式都允许较less的耦合,但是完全不同。

@cdc出色地解释了意图上的差异。

我会在上面添加一些更多的信息。

观察者 :启用一个对象中事件的通知给不同的对象集合(不同类别的实例)

调解员 :集中对象集之间的通信,从一个特定的类创build。

Mediator模式的结构从dofactory :

在这里输入图像说明

调解员 :定义同事之间沟通的界面。

同事 :是一个抽象的类,它定义了要在同事之间传递的事件

具体执行者:通过协调同事对象和维护同事来实现合作行为

ConcreteColleague :实施由其他同事产生的调解员收到的通知操作

一个现实世界的例子:

您正在维护Mesh拓扑中的计算机networking。 如果添加新计算机或删除了现有计算机,则该networking中的所有其他计算机都应了解这两个事件。

让我们看看Mediator模式如何适应它。

代码片段:

 import java.util.List; import java.util.ArrayList; /* Define the contract for communication between Colleagues. Implementation is left to ConcreteMediator */ interface Mediator{ public void register(Colleague colleague); public void unregister(Colleague colleague); } /* Define the contract for notification events from Mediator. Implementation is left to ConcreteColleague */ abstract class Colleague{ private Mediator mediator; private String name; public Colleague(Mediator mediator,String name){ this.mediator = mediator; this.name = name; } public String toString(){ return name; } public abstract void receiveRegisterNotification(Colleague colleague); public abstract void receiveUnRegisterNotification(Colleague colleague); } /* Process notification event raised by other Colleague through Mediator. */ class ComputerColleague extends Colleague { private Mediator mediator; public ComputerColleague(Mediator mediator,String name){ super(mediator,name); } public void receiveRegisterNotification(Colleague colleague){ System.out.println("New Computer register event with name:"+colleague+ ": received @"+this); // Send further messages to this new Colleague from now onwards } public void receiveUnRegisterNotification(Colleague colleague){ System.out.println("Computer left unregister event with name:"+colleague+ ":received @"+this); // Do not send further messages to this Colleague from now onwards } } /* Act as a central hub for communication between different Colleagues. Notifies all Concrete Colleagues on occurrence of an event */ class NetworkMediator implements Mediator{ List<Colleague> colleagues = new ArrayList<Colleague>(); public NetworkMediator(){ } public void register(Colleague colleague){ colleagues.add(colleague); for (Colleague other : colleagues){ if ( other != colleague){ other.receiveRegisterNotification(colleague); } } } public void unregister(Colleague colleague){ colleagues.remove(colleague); for (Colleague other : colleagues){ other.receiveUnRegisterNotification(colleague); } } } public class MediatorPatternDemo{ public static void main(String args[]){ Mediator mediator = new NetworkMediator(); ComputerColleague colleague1 = new ComputerColleague(mediator,"Eagle"); ComputerColleague colleague2 = new ComputerColleague(mediator,"Ostrich"); ComputerColleague colleague3 = new ComputerColleague(mediator,"Penguin"); mediator.register(colleague1); mediator.register(colleague2); mediator.register(colleague3); mediator.unregister(colleague1); } } 

输出:

 New Computer register event with name:Ostrich: received @Eagle New Computer register event with name:Penguin: received @Eagle New Computer register event with name:Penguin: received @Ostrich Computer left unregister event with name:Eagle:received @Ostrich Computer left unregister event with name:Eagle:received @Penguin 

说明:

  1. Eagle首先通过注册事件添加到networking中。 自从鹰是第一个以来,没有任何其他同事的通知。
  2. 鸵鸟被添加到networking时, Eagle被通知:输出的第一行现在被渲染。
  3. 企鹅joinnetworking时, EagleOstrich已经被通知:输出的2行和3行现在被渲染。
  4. 老鹰通过注册事件离开networking时, 鸵鸟企鹅都被通知了。 第4行和第5行的输出现在呈现。

虽然两者都用于有组织的方式来讲述状态变化,但它们在结构和语义上略有不同。

观察者用于从对象本身广播特定对象的状态改变。 所以这个变化发生在负责发信号的中心对象上。 但是,在Mediator中,状态变化可以在任何对象中发生,但是从中介者广播。 所以stream量有所不同。 但是,我不认为这会影响我们的代码行为。 我们可以使用一个或另一个来实现相同的行为。 另一方面,这种差异可能会对代码的概念理解产生一些影响。

看,模式的主要目的是在开发者之间创build一个共同的语言。 所以,当我看到一个中介时,我个人理解了试图通过一个中介/中心进行通信以减less通信噪音(或促进SRP)的多个要素,并且每个对象在具有发信号通知状态变化的能力方面同等重要。 例如,想到多架飞机正在接近机场。 每个人都应该通过塔(调解员)沟通,而不是相互沟通。 (想象一下着陆时有1000架飞机相互通信)

然而,当我看到一个观察者时,这意味着我可能会关心一些状态变化,应该注册/订阅来监听特定的状态变化。 有一个中央对象负责信号状态的变化。 例如,如果我在从A到B的路上关心某个特定的机场,我可以在这个机场登记,看一些播出的事件,比如说有空的跑道或类似的东西。

希望很清楚。

Interesting Posts