我一直在阅读四人帮,以解决我的一些问题,并遇到了中介者模式。
我之前在我的项目中使用了观察者来制作一些GUI应用程序。我有点困惑,因为我没有发现两者之间有很大的区别。我浏览了一下,但没有找到任何明确区分两者的好例子。
能否有人通过一些清晰区分两者的好例子来帮助我区分它们?
我一直在阅读四人帮,以解决我的一些问题,并遇到了中介者模式。
我之前在我的项目中使用了观察者来制作一些GUI应用程序。我有点困惑,因为我没有发现两者之间有很大的区别。我浏览了一下,但没有找到任何明确区分两者的好例子。
能否有人通过一些清晰区分两者的好例子来帮助我区分它们?
观察者模式: 定义对象之间的一对多依赖关系,以使得当一个对象改变状态时,所有依赖于它的对象都会被自动通知和更新。
中介者模式: 定义一个对象来封装一组对象之间的交互方式。中介者通过保持对象不直接相互引用来促进松散耦合,并且让您可以独立地改变它们的交互方式。
来源:dofactory
示例:
观察者模式: 类A可以注册零个或多个类型为O的观察者。当A中的某些内容发生变化时,它会通知所有观察者。
中介者模式: 您拥有一些类X的实例(甚至可能是几种不同类型:X、Y和Z),它们希望相互通信(但您不希望每一个类都有显式的引用关系),因此您创建了一个中介者类M。每个X类实例都有一个对共享M实例的引用,通过它可以与其他X类实例(或X、Y和Z)进行通信。
客户端1:嘿主题,你什么时候改变?
客户端2:你什么时候改变了主题?我没有注意到!
客户端3:我知道主题已经改变了。
客户端们保持沉默。
过了一段时间...
主题:亲爱的客户端们,我已经改变了!
客户端1:嘿出租车1,带我去某个地方。
客户端2:嘿出租车1,带我去某个地方。
客户端1:嘿出租车2,带我去某个地方。
客户端2:嘿出租车2,带我去某个地方。
客户端1:嘿出租车中心,请给我安排一辆出租车。
客户端2:嘿出租车中心,请给我安排一辆出租车。
这些模式用于不同的情况:
当您有两个具有某些依赖关系的子系统,并且其中一个子系统需要进行更改时,中介者模式就会被使用。由于您可能不想更改依赖于其他子系统的系统,因此您可能希望引入一个中介者来解耦它们之间的依赖关系。这样,当其中一个子系统发生更改时,您只需更新中介者。
观察者模式则用于当一个类想要允许其他类注册自己并在事件发生时接收通知时使用,例如ButtonListener等。
这两种模式都允许较少的耦合,但是它们是非常不同的。
让我们来举个例子:假设你想构建两个应用程序:
在构建聊天应用时,您将选择 中介者
设计模式。
为什么会选择 中介者
?只需看一下其定义即可:
使用中介者模式,对象之间的通信被封装在一个中介者对象内。对象不再直接相互通信,而是通过中介者进行通信。这减少了相互通信的对象之间的依赖关系,从而减少了耦合。
这种魔法是如何运作的呢?首先,我们将创建聊天中介者并使人物对象注册到它上面,因此它将具有每个单个人物对象的双向连接(人物可以使用聊天中介者发送消息,因为它可以访问它,并且聊天中介者将访问人物对象的接收方法,因为它也可以访问它)。
function Person(name) {
let self = this;
this._name = name;
this._chat = null;
this._receive(from, message) {
console.log("{0}: '{1}'".format(from.name(), message));
}
this._send(to, message) {
this._chat.message(this, to, message);
}
return {
receive: (from, message) => { self._receive(from, message) },
send: (to, message) => { self._send(to, message) },
initChat: (chat) => { this._chat = chat; },
name: () => { return this._name; }
}
}
function ChatMediator() {
let self = this;
this._persons = [];
return {
message: function (from, to, message) {
if (self._persons.indexOf(to) > -1) {
self._persons[to].receive(from, message);
}
},
register: function (person) {
person.initChat(self);
self._persons.push(person);
}
unRegister: function (person) {
person.initChat(null);
delete self._persons[person.name()];
}
}
};
//Usage:
let chat = new ChatMediator();
let colton = new Person('Colton');
let ronan = new Person('Ronan');
chat.register(colton);
chat.register(ronan);
colton.send(ronan, 'Hello there, nice to meet you');
ronan.send(colton, 'Nice to meet you to');
colton.send(ronan, 'Goodbye!');
chat.unRegister(colton);
在构建911呼叫应用程序时,您将选择观察者
设计模式。
观察者
对象都希望在紧急情况下得到通知,以便他可以前往地址并提供帮助。可观察的
引用每个救护车观察者
的对象,并在需要帮助(或生成事件)时通知它们。为什么我们会更喜欢观察者
?只需看一下其定义:
一个名为主题的对象维护其依赖项列表,称为观察者,并通过调用它们的方法之一自动通知它们任何状态更改。
function AmbulanceObserver(name) {
let self = this;
this._name = name;
this._send(address) {
console.log(this._name + ' has been sent to the address: ' + address);
}
return {
send: (address) => { self._send(address) },
name: () => { return this._name; }
}
}
function OperatorObservable() {
let self = this;
this._ambulances = [];
return {
send: function (ambulance, address) {
if (self._ambulances.indexOf(ambulance) > -1) {
self._ambulances[ambulance].send(address);
}
},
register: function (ambulance) {
self._ambulances.push(ambulance);
}
unRegister: function (ambulance) {
delete self._ambulances[ambulance.name()];
}
}
};
//Usage:
let operator = new OperatorObservable();
let amb111 = new AmbulanceObserver('111');
let amb112 = new AmbulanceObserver('112');
operator.register(amb111);
operator.register(amb112);
operator.send(amb111, '27010 La Sierra Lane Austin, MN 000');
operator.unRegister(amb111);
operator.send(amb112, '97011 La Sierra Lane Austin, BN 111');
operator.unRegister(amb112);
@cdc解释了意图的差异,非常出色。
我会在此基础上添加一些信息。
观察者模式:使一个对象中的事件通知到不同类的实例中。
中介者模式:集中管理从特定类创建的一组对象之间的通信。
来自 dofactory 的中介者模式结构:
中介者:定义 Colleagues 之间通信的接口。
Colleague:是一个抽象类,其定义了要在 Colleagues 之间通信的事件。
ConcreteMediator:通过协调 Colleague 对象实现协作行为,并维护其 colleagues。
ConcreteColleague:实现通过 Mediator 接收到的通知操作,该操作由其他 Colleague 生成。
一个真实的例子:
您正在维护一个网状拓扑结构的计算机网络。如果添加了新计算机或删除了现有计算机,则该网络中的所有其他计算机都应该知道这两个事件。
让我们看看中介者模式如何适用于此。
代码片段:
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
解释:
这是一个关于Observer和Mediator的解释。从技术上讲,它们都可以用于提供组件通信的解耦方式,但使用方式不同。
当observer
通知已经 订阅 的组件有状态变化时(例如创建新的数据库记录),mediator
命令已经 注册 的组件执行与业务逻辑流程相关的操作(例如向用户发送密码重置邮件)。
Programmers.StackExchange
被拒绝了,但是我在那里发布了一个类似的帖子,因为我对答案很感兴趣。您可能会发现其中一些答案很有趣。 :) - RachelChangeManager
示例来说明。请参见:https://paginas.fe.up.pt/~aaguiar/as/gof/hires/pat5g.htm#samplecode - robi-y