Lets go by an example: consider you want to build two application:
- Chat application.
- Emergency ambulance operator application.
mediator
Building the chat application you will be choosing the mediator
design pattern.
- The persons may be joining and leaving the chat at any given time, so it does not make any sense to keep direct reference between two persons chatting.
- We still need to facilitate a communication between two persons and allow them have a chat.
Why will we prefer the mediator
? just have a look at its definition:
With the mediator pattern, communication between objects is
encapsulated within a mediator object. Objects no longer communicate
directly with each other, but instead communicate through the
mediator. This reduces the dependencies between communicating objects,
thereby reducing coupling.
How is the magic works? First we will create the chat mediator and make the persons objects register to it, so it will have two directional connection with every single person (the person can send message using the chat mediator cause it ha access to it, and the chat mediator will access the received method of the person object cause he also has access to it)
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);
observer
Building the 911 call application you will be choosing the observer
design pattern.
- Each ambulance
observer
object wishes to be informed when there is an emergency state, so he can drive the address and give help.
- The emergency operator
observable
keep reference to each on of the ambulance observers
and notify them when help is needed (or generating event).
Why will we prefer the observer
? just have a look at its definition:
An object, called the subject, maintains a list of its dependents,
called observers, and notifies them automatically of any state
changes, usually by calling one of their methods.
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);
The Differences:
- The chat
mediator
has two way communication between the persons objects (send and receive) wheres the operator observable
has only one way communication (It tell the ambulance observer
to drive and finish).
- The chat
mediator
can make the persons objects interact between them (even if it not a direct communication), the ambulances observers
only registers to the operator observable
events.
- Each person object has a reference to the chat
mediator
, and also the chat mediator
keep reference to the every one of the persons. Wheres the ambulance observer
does not keep reference to the operator observable
, only the operator observable
keep reference to every ambulance observer
.