I have been reading the Gang Of Four, in order to solve some of my problems and came across the Mediator pattern.
I had earlier use
How About this explanation Technically both Observer and Mediator are the same and are used to provide decoupled way for component communication, but usage is different.
While obeserver
notifies subscribed components about state changes (creation of new db record, for instance), the mediator
commands registered components to do something related to business logic flow (sending email to user for password reset).
Lets go by an example: consider you want to build two application:
Building the chat application you will be choosing the mediator
design pattern.
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(colton, 'Hello there, nice to meet you');
ronan.send(ronan, 'Nice to meet you to');
colton.send(colton, 'Goodbye!');
chat.unRegister(colton);
Building the 911 call application you will be choosing the observer
design pattern.
observer
object wishes to be informed when there is an emergency state, so he can drive the address and give help. 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);
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).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.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
.