Javascript. Mediator pattern

Паттерн Посредник (Mediator pattern) используется для централизации сложных взаимодействий и управляющих операций между объектами. Использование данного паттерна позволяет снизить количество зависимостей между объектами в системе (так называемые - коллеги), а взаимодействие между ними осуществляет непосредственно специальный объект (посредник или медиатор). Это улучшает сопровождение кода, так как мы всегда можем реализовать посредник с требуемыми критериями. Данный паттерн относится к поведенческим паттернам. В самом простом виде диаграмма классов данного паттерна выглядит следующим образом.


Заметим, что коллеги знают только о посреднике, в котором инкапсулирована логика взаимодействия. При возрастании объектов в системе данная логика может усложниться, что является одним из минусов паттерна. Рассмотрим ряд пример реализации данного паттерна. Пример первый. В системе имеются пользователи, необходимо наладить между ними общение, например в виде чата. Одна из реализаций.

/* Colleagues */

var User = function (mediator, name) {
this.mediator = mediator;
this.name = name;
};

User.prototype.send = function (msg) {
console.log(this.name + ": sending message: " + msg);
this.mediator.sendMessage(msg, this);
};

User.prototype.receive = function (msg) {
console.log(this.name + ": received message: " + msg);
};

/* ConcreteMediator */

var chatMediator = {
users: [],
addUser: function (user) {
this.users.push(user);
},
sendMessage: function (msg, user) {
for (var i = 0; i < this.users.length; i++) {
if (this.users[i] !== user) {
this.users[i].receive(msg);
}
}
}
};

var Adam = new User(chatMediator, "Adam");
var Poll = new User(chatMediator, "Poll");
var Jon = new User(chatMediator, "Jon");
var Allan = new User(chatMediator, "Allan");

chatMediator.addUser(Adam);
chatMediator.addUser(Poll);
chatMediator.addUser(Jon);
chatMediator.addUser(Allan);

Adam.send("Hi All");

На выходе:

Adam: sending message: Hi All
Poll: received message: Hi All
Jon: received message: Hi All
Allan: received message: Hi All

Пример второй. Ниже будет представлена реализация простой игры - два игрока в течении 30 секунд должны нажимать свою кнопку (1 или 2), по окончании времени побеждает тот, кто успел нажать как можно больше раз. В реализации игры будут участвовать объекты-коллеги и посредник, которые представлены на следующем рисунке.


/* Colleagues */

var Player = function (name) {
this.points = 0;
this.name = name;
};
Player.prototype.play = function () {
this.points += 1;
mediator.played();
};

/* ConcreteColleague */

var scoreboard = {

// element of HTML, which should be updated
element: document.getElementById('results'),

// updates the score on the screen
update: function (score) {
var i, msg = '';
for (i in score) {
if (score.hasOwnProperty(i)) {
msg += '<p><strong>' + i + '<\/strong>';
msg += score[i];
msg += '<\/p>';
}
}
this.element.innerHTML = msg;
}
};

/* ConcreteMediator */

var mediator = {

// all players
players: {},

// initialization
setup: function () {
var players = this.players;
players.home = new Player('Home');
players.guest = new Player('Guest');
},

// updates the score, if someone of the players made the move
played: function () {
var players = this.players,
score = {
Home:  players.home.points,
Guest: players.guest.points
};

scoreboard.update(score);
},

// handler of user actions
keypress: function (e) {
e = e || window.event;   // IE
if (e.which === 49) { // key "1"
mediator.players.home.play();
return;
}
if (e.which === 48) { // key "0"
mediator.players.guest.play();
return;
}
}
};

/* testing */

var Application = function () {
this.run = function () {
// Start!
mediator.setup();
window.onkeypress = mediator.keypress;

// The game ends after 30 seconds
setTimeout(function () {
window.onkeypress = null;
alert('Game over!');
}, 30000);
};
};

var game = new Application;
game.run();

Приятной Вам игры :)