The role of the mediator pattern is to decouple objects from each other.

introduce

By adding a mediator object, all related objects communicate through the mediator object rather than referring to each other, so when an object changes, the mediator object only needs to be notified. The mediator loosens the coupling between objects and can change their interactions independently. The mediator pattern turns the netted many-to-many relationship into a relatively simple one-to-many relationship.

The mediator pattern is an implementation of the least knowledge principle (Demeter’s law). It means that an object should know as little as possible about another object (similar to not talking to strangers).

For example

Use a small game to illustrate the use of the mediator model.

** Rules of the game: ** Two teams of players play against each other, the game ends when one player dies, and the opponent is notified of victory.

Common implementation

var players = [];
// Write the Hero function; The code is as follows:

var players = []; // Define an array to hold all players
function Hero(name,teamColor) {
    this.friends = [];    // Save the teammate list
    this.enemies = [];    // Save the list of enemies
    this.state = 'live';  // Player state
    this.name = name;     // Character name
    this.teamColor = teamColor; // Team color
}
Hero.prototype.win = function(){
    console.log("win:" + this.name);
};
Hero.prototype.lose = function(){
    console.log("lose:" + this.name);
};
Hero.prototype.die = function(){
    // All dead party members are alive by default
    var all_dead = true;
    this.state = 'dead'; // Set the player state to dead
    for(var i = 0,ilen = this.friends.length; i < ilen; i+=1) {
        // The game is not over if a teammate is still alive
        if(this.friends[i].state ! = ='dead') {
            all_dead = false; 
            break; }}if(all_dead) {
        this.lose();  // All teammates die, the game ends
        // Loop to inform all players of game failure
        for(var j = 0,jlen = this.friends.length; j < jlen; j+=1) {
            this.friends[j].lose();
        }
        // Notify all enemies of game victory
        for(var j = 0,jlen = this.enemies.length; j < jlen; j+=1) {
            this.enemies[j].win(); }}}// Define a factory class to create players
var heroFactory = function(name,teamColor) {
    var newPlayer = new Hero(name,teamColor);
    for(var i = 0,ilen = players.length; i < ilen; i+=1) {
        // If the player is on the same team
        if(players[i].teamColor === newPlayer.teamColor) {
            // Add teammates to each other's list
            players[i].friends.push(newPlayer);
            newPlayer.friends.push(players[i]);
        }else {
            // Add each other to the enemies list
            players[i].enemies.push(newPlayer);
            newPlayer.enemies.push(players[i]);
        }
    }
    players.push(newPlayer);
    return newPlayer;
};
        / / the red team
var p1 = heroFactory("aa".'red'),
    p2 = heroFactory("bb".'red'),
    p3 = heroFactory("cc".'red'),
    p4 = heroFactory("dd".'red');
        
/ / blues'
var p5 = heroFactory("ee".'blue'),
    p6 = heroFactory("ff".'blue'),
    p7 = heroFactory("gg".'blue'),
    p8 = heroFactory("hh".'blue');
// Let all red team players die
p1.die();
p2.die();
p3.die();
p4.die();
// lose:dd lose:aa lose:bb lose:cc
// win:ee win:ff win:gg win:hh
Copy the code

The mediator pattern is implemented

Players to remove with the players to the coupling between the code and put all of the logical operation in the mediator object in processing, a player any operation does not need to traverse to notify the other player, but just need to broker to send a message to broker for processing after received the message, after processing the message object will reduce the processing result feedback to other players.

var players = []; // Define an array to hold all players
function Hero(name,teamColor) {
    this.state = 'live';  // Player state
    this.name = name;     // Character name
    this.teamColor = teamColor; // Team color
}
Hero.prototype.win = function(){
    / / won
    console.log("win:" + this.name);
};
Hero.prototype.lose = function(){
    / / lost
    console.log("lose:" + this.name);
};
/ / death
Hero.prototype.die = function(){
    this.state = 'dead';
    // Send a message to the broker, the player dies
    playerDirector.ReceiveMessage('playerDead'.this);
}
// Remove the player
Hero.prototype.remove = function(){
    // Send a message to the broker to remove a player
    playerDirector.ReceiveMessage('removePlayer'.this);
};
// Players change teams
Hero.prototype.changeTeam = function(color) {
    // Send a message to the broker and the player changes teams
    playerDirector.ReceiveMessage('changeTeam'.this,color);
};
// Define a factory class to create players
var heroFactory = function(name,teamColor) {
    // Create a new player object
    var newHero = new Hero(name,teamColor);
    // Send a message to the broker to add new players
    playerDirector.ReceiveMessage('addPlayer',newHero);
    return newHero;
};
var playerDirector = (function(){
    var players = {},  // Save all players
        operations = {}; // Actions that the mediator can perform
    // Add a new player action
    operations.addPlayer = function(player) {
        // Get the colors of the player's teammates
        var teamColor = player.teamColor;
        // If this color does not already have a team, create a new team
        players[teamColor] = players[teamColor] || [];
        // Add players to the team
        players[teamColor].push(player);
     };
    // Remove a player
    operations.removePlayer = function(player){
        // Get the team color
        var teamColor = player.teamColor,
        // Get all members of the team
        teamPlayers = players[teamColor] || [];
        / / traverse
        for(var i = teamPlayers.length - 1; i> =0; i--) {
            if(teamPlayers[i] === player) {
                teamPlayers.splice(i,1); }}};// Players change teams
    operations.changeTeam = function(player,newTeamColor){
        // Delete from the original team first
        operations.removePlayer(player);
        // Then change the team color
        player.teamColor = newTeamColor;
        // Add to the team
        operations.addPlayer(player);
    };
    // The player dies
operations.playerDead = function(player) {
    var teamColor = player.teamColor,
    // The player's team
    teamPlayers = players[teamColor];

    var all_dead = true;
    / / traverse
    for(var i = 0,player; player = teamPlayers[i++]; ) {
        if(player.state ! = ='dead') {
            all_dead = false;
            break; }}// If all_dead is true, all dead
    if(all_dead) {
        for(var i = 0, player; player = teamPlayers[i++]; ) {
            // All players lose
            player.lose();
        }
        for(var color in players) {
            if(color ! == teamColor) {// This is another team
                // Get the team's player
                var teamPlayers = players[color];
                for(var i = 0,player; player = teamPlayers[i++]; ) {
                    player.win(); // Traversal notifies other players that win}}}}};var ReceiveMessage = function(){
    // arguments Gets the first argument for the message name
    var message = Array.prototype.shift.call(arguments);
    operations[message].apply(this.arguments);
};
return {
    ReceiveMessage: ReceiveMessage }; }) ();/ / the red team
var p1 = heroFactory("aa".'red'),
    p2 = heroFactory("bb".'red'),
    p3 = heroFactory("cc".'red'),
        p4 = heroFactory("dd".'red');
        
    / / blues'
    var p5 = heroFactory("ee".'blue'),
        p6 = heroFactory("ff".'blue'),
        p7 = heroFactory("gg".'blue'),
        p8 = heroFactory("hh".'blue');
    // Let all red team players die
    p1.die();
    p2.die();
    p3.die();
    p4.die();
    // lose:aa lose:bb lose:cc lose:dd 
   // win:ee win:ff win:gg win:hh
Copy the code

reference

  • JavaScript design patterns and development practices