Skip to content

Instantly share code, notes, and snippets.

@addyosmani
Created February 15, 2012 17:01

Revisions

  1. addyosmani revised this gist Feb 15, 2012. 1 changed file with 13 additions and 1 deletion.
    14 changes: 13 additions & 1 deletion mediator.md
    Original file line number Diff line number Diff line change
    @@ -98,12 +98,24 @@ Here are two sample uses of the implementation from above. It's effectively cent
    ```

    ##Advantages & Disadvantages

    The benefits of the Mediator pattern are that that it simplifies object interaction and can aid with decoupling those using it as a communication hub. In the above example, rather than using the Observer pattern to explicitly set many-to-many listeners and events, a Mediator allows you to broadcast events globally between subscribers and publishers. Broadcasted events can be handled by any number of modules at once and a mediator can used for a number of other purposes such as permissions management, given that it can control what messages can be subscribed to and which can be broadcast.

    Perhaps the biggest downside of using the Mediator pattern is that it can introduce a single point of failure. Placing a Mediator between modules can also cause a performance hit as they are always communicating indirectly.Because of the nature of loose coupling, its difficult to establish how a system might react by only looking at the broadcasts. That said, it's useful to remind ourselves that decoupled systems have a number of other benefits - if our modules communicated with each other directly, changes to modules (e.g another module throwing an exception) could easily have a domino effect on the rest of your application. This problem is less of a concern with decoupled systems.

    At the end of the day, tight coupling causes all kinds of headaches and this is just another alternative solution, but one which can work very well if implemented correctly.

    ##Mediator Vs. Observer

    Developers often wonder what the differences are between the Mediator pattern and the Observer pattern. Admittedly, there is a bit of overlap, but let's refer back to the GoF for an explanation:

    "In the Observer pattern, there is no single object that encapsulates a constraint. Instead, the Observer and the Subject must cooperate to maintain the constraint. Communication patterns are determined by the way observers and subjects are interconnected: a single subject usually has many observers, and sometimes the observer of one subject is a subject of another observer. The Mediator pattern centralizes rather than distributes. It places the responsibility for maintaining a constraint squarely in the mediator."
    "In the Observer pattern, there is no single object that encapsulates a constraint. Instead, the Observer and the Subject must cooperate to maintain the constraint. Communication patterns are determined by the way observers and subjects are interconnected: a single subject usually has many observers, and sometimes the observer of one subject is a subject of another observer."

    The Mediator pattern centralizes rather than simply just distributing. It places the responsibility for maintaining a constraint squarely in the mediator.

    ##Mediator Vs. Facade

    Some developers may also wonder whether there are similarities between the Mediator and Facade patterns. They do both abstract the functionality of existing modules, but there are some subtle differences.

    The Mediator centralizes communication between colleagues (modules) where it's explicitly referenced by these modules. In a sense this is multidirectional. The Facade however just defines a simpler interface to a module or system but doesn't add any additional functionality. Other modules in the system aren't directly aware of the concept of a facade and could be considered unidirectional.
  2. addyosmani revised this gist Feb 15, 2012. 1 changed file with 21 additions and 15 deletions.
    36 changes: 21 additions & 15 deletions mediator.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,6 @@
    The Mediator is a behavioural design pattern that allow us to expose a unified interface through which the different parts of a system may communicate. If it appears a system may have too many direct relationships between modules, it may be time to have a central point of control that modules communicate through instead. The Mediator promotes loose coupling by ensuring that instead of modules referring to each other explicitly, their interaction is handled through this central point.
    The dictionary refers to a Mediator as 'a neutral party who assists in negotiations and conflict resolution'.

    In software engineering, a Mediator is a behavioural design pattern that allow us to expose a unified interface through which the different parts of a system may communicate. If it appears a system may have too many direct relationships between modules, it may be time to have a central point of control that modules communicate through instead. The Mediator promotes loose coupling by ensuring that instead of modules referring to each other explicitly, their interaction is handled through this central point.

    If you would prefer an analogy, consider a typical airport traffic control system. A tower (Mediator) handles what planes (modules) can take off and land because all communications are done from the planes to the control tower, rather than from plane-to-plane. A centralized controller is key to the success of this system and that's really the role a mediator plays in software design.

    @@ -68,28 +70,32 @@ var mediator = (function(){
    Here are two sample uses of the implementation from above. It's effectively centralized Publish/Subscribe where a mediated implementation of the Observer pattern is used:

    ```
    //Pub/sub on a centralized mediator
    mediator.name = "tim";
    mediator.subscribe('nameChange', function(arg){
    console.log(this.name);
    this.name = arg;
    console.log(this.name);
    });
    (function(Mediator){
    mediator.publish('nameChange', 'david'); //tim, david
    function initialize(){
    //Pub/sub via third party mediator
    // Set a default value for 'name'
    mediator.name = "tim";
    var obj = { name: 'sam' };
    mediator.installTo(obj);
    obj.subscribe('nameChange', function(arg){
    // Subscribe to an event called 'nameChange' with
    // a callback function which will log the original
    // name and (if everything works) the new name
    mediator.subscribe('nameChange', function(arg){
    console.log(this.name);
    this.name = arg;
    console.log(this.name);
    });
    });
    }
    function updateName(){
    // Publish/Broadcast the 'nameChange' event with the new data
    mediator.publish('nameChange', 'david'); // tim, david
    }
    })(mediator);
    obj.publish('nameChange', 'john'); //sam, john
    ```

    The benefits of the Mediator pattern are that that it simplifies object interaction and can aid with decoupling those using it as a communication hub. In the above example, rather than using the Observer pattern to explicitly set many-to-many listeners and events, a Mediator allows you to broadcast events globally between subscribers and publishers. Broadcasted events can be handled by any number of modules at once and a mediator can used for a number of other purposes such as permissions management, given that it can control what messages can be subscribed to and which can be broadcast.
  3. addyosmani revised this gist Feb 15, 2012. 1 changed file with 40 additions and 9 deletions.
    49 changes: 40 additions & 9 deletions mediator.md
    Original file line number Diff line number Diff line change
    @@ -1,19 +1,47 @@
    Mediators are used when the communication between modules may be complex, but is still well defined. If it appears a system may have too many relationships between modules in your code, it may be time to have a central point of control, which is where the pattern fits in. If you would prefer an analogy, consider a typical airport traffic control system. A tower handles what planes can take off and land because all communications are done from the planes to the control tower, rather than from plane-to-plane. A centralized controller is key to the success of this system and that's really the role a mediator plays in software design.
    The Mediator is a behavioural design pattern that allow us to expose a unified interface through which the different parts of a system may communicate. If it appears a system may have too many direct relationships between modules, it may be time to have a central point of control that modules communicate through instead. The Mediator promotes loose coupling by ensuring that instead of modules referring to each other explicitly, their interaction is handled through this central point.

    In real-world terms, a mediator encapsulates how disparate modules interact with each other by acting as an intermediary. The pattern also promotes loose coupling by preventing objects from referring to each other explicitly - in our system, this helps to solve our module inter-dependency issues.
    If you would prefer an analogy, consider a typical airport traffic control system. A tower (Mediator) handles what planes (modules) can take off and land because all communications are done from the planes to the control tower, rather than from plane-to-plane. A centralized controller is key to the success of this system and that's really the role a mediator plays in software design.

    It's been described in the GoF book, Design Patterns: Elements of Reusable Object-Oriented Software as a behavioural pattern with the following goal: "Define an object that encapsulated how a set of objects interact. The Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently."
    In real-world terms, a mediator encapsulates how disparate modules interact with each other by acting as an intermediary. At it's most basic, a mediator could be implemented as a central base for accessing functionality as follows:

    Example: This is a possible implementation of the mediator pattern based on previous work by @rpflorence
    ```
    // Our app namespace can act as a mediator
    var app = app || {};
    // Communicate through the mediator for Ajax requests
    app.sendRequest = function ( options ) {
    return $.ajax($.extend({}, options);
    }
    // When a request for a URL resolves, do something with the view
    app.populateView = function( url, view ){
    $.when(app.sendRequest({url: url, method: 'GET'})
    .then(function(){
    //populate the view
    });
    }
    // Empty a view of any content it may contain
    app.resetView = function( view ){
    view.html('');
    }
    ```

    That said, in the JavaScript world it's become quite common for the Mediator to act as a messaging bus on top of the Observer-pattern. Rather than modules calling a Publish/Subscribe implementation, they'll use a Mediator with these capabilities built in instead. A possible implementation of this (based on work by Ryan Florence) could look as follows:

    ```
    var mediator = (function(){
    // Subscribe to an event, supply a callback to be executed
    // when that event is broadcast
    var subscribe = function(channel, fn){
    if (!mediator.channels[channel]) mediator.channels[channel] = [];
    mediator.channels[channel].push({ context: this, callback: fn });
    return this;
    },
    // Publish/broadcast an event to the rest of the application
    publish = function(channel){
    if (!mediator.channels[channel]) return false;
    var args = Array.prototype.slice.call(arguments, 1);
    @@ -37,7 +65,7 @@ var mediator = (function(){
    }());
    ```

    Example: Here are two sample uses of the implementation from above. It's effectively managed publish/subscribe:
    Here are two sample uses of the implementation from above. It's effectively centralized Publish/Subscribe where a mediated implementation of the Observer pattern is used:

    ```
    //Pub/sub on a centralized mediator
    @@ -51,7 +79,6 @@ mediator.subscribe('nameChange', function(arg){
    mediator.publish('nameChange', 'david'); //tim, david
    //Pub/sub via third party mediator
    var obj = { name: 'sam' };
    @@ -65,8 +92,12 @@ obj.subscribe('nameChange', function(arg){
    obj.publish('nameChange', 'john'); //sam, john
    ```

    The benefits of the Mediator pattern are that that it simplifies object interaction and can aid with decoupling those using it as a communication hub. Instead of using the Observer pattern to explicitly set many-to-many listeners and events, a Mediator allows you to broadcast events globally between subscribers and publishers. Broadcasted events can be handled by any number of modules at once and a mediator can used for a number of other purposes such as permissions management, given that it can control what messages can be subscribed to and which can be broadcast.
    The benefits of the Mediator pattern are that that it simplifies object interaction and can aid with decoupling those using it as a communication hub. In the above example, rather than using the Observer pattern to explicitly set many-to-many listeners and events, a Mediator allows you to broadcast events globally between subscribers and publishers. Broadcasted events can be handled by any number of modules at once and a mediator can used for a number of other purposes such as permissions management, given that it can control what messages can be subscribed to and which can be broadcast.

    Perhaps the biggest downside of using the Mediator pattern is that it can introduce a single point of failure. Placing a Mediator between modules can also cause a performance hit as they are always communicating indirectly.Because of the nature of loose coupling, its difficult to establish how a system might react by only looking at the broadcasts. That said, it's useful to remind ourselves that decoupled systems have a number of other benefits - if our modules communicated with each other directly, changes to modules (e.g another module throwing an exception) could easily have a domino effect on the rest of your application. This problem is less of a concern with decoupled systems.

    At the end of the day, tight coupling causes all kinds of headaches and this is just another alternative solution, but one which can work very well if implemented correctly.

    Perhaps the biggest downside of using the Mediator pattern is that it can introduce a single point of failure and can in some cases become difficult to manage effectively. It's disadvantages also include that by adding a mediator between modules, they must always communicate indirectly. This can cause a very minor performance drop - because of the nature of loose coupling, its difficult to establish how a system might react by only looking at the broadcasts.
    Developers often wonder what the differences are between the Mediator pattern and the Observer pattern. Admittedly, there is a bit of overlap, but let's refer back to the GoF for an explanation:

    At the end of the day, tight coupling causes all kinds of headaches and this is just another alternative solution, but one which can work very well if implemented correctly.
    "In the Observer pattern, there is no single object that encapsulates a constraint. Instead, the Observer and the Subject must cooperate to maintain the constraint. Communication patterns are determined by the way observers and subjects are interconnected: a single subject usually has many observers, and sometimes the observer of one subject is a subject of another observer. The Mediator pattern centralizes rather than distributes. It places the responsibility for maintaining a constraint squarely in the mediator."
  4. addyosmani revised this gist Feb 15, 2012. 1 changed file with 8 additions and 18 deletions.
    26 changes: 8 additions & 18 deletions mediator.md
    Original file line number Diff line number Diff line change
    @@ -1,25 +1,9 @@
    The mediator pattern is best introduced with a simple analogy - think of your typical airport traffic control. The tower handles what planes can take off and land because all communications are done from the planes to the control tower, rather than from plane-to-plane. A centralized controller is key to the success of this system and that's really what a mediator is.
    Mediators are used when the communication between modules may be complex, but is still well defined. If it appears a system may have too many relationships between modules in your code, it may be time to have a central point of control, which is where the pattern fits in. If you would prefer an analogy, consider a typical airport traffic control system. A tower handles what planes can take off and land because all communications are done from the planes to the control tower, rather than from plane-to-plane. A centralized controller is key to the success of this system and that's really the role a mediator plays in software design.

    Mediators are used when the communication between modules may be complex, but is still well defined. If it appears a system may have too many relationships between modules in your code, it may be time to have a central point of control, which is where the pattern fits in. In real-world terms, a mediator encapsulates how disparate modules interact with each other by acting as an intermediary. The pattern also promotes loose coupling by preventing objects from referring to each other explicitly - in our system, this helps to solve our module inter-dependency issues.
    In real-world terms, a mediator encapsulates how disparate modules interact with each other by acting as an intermediary. The pattern also promotes loose coupling by preventing objects from referring to each other explicitly - in our system, this helps to solve our module inter-dependency issues.

    It's been described in the GoF book, Design Patterns: Elements of Reusable Object-Oriented Software as a behavioural pattern with the following goal: "Define an object that encapsulated how a set of objects interact. The Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently."

    The benefits of this pattern are that that it simplifies object interaction and can aid with decoupling those using it as a communication hub. Instead of using the Observer pattern to explicitly set many-to-many listeners and events, a Mediator allows you to broadcast events globally between subscribers and publishers. Perhaps the biggest downside of using the Mediator pattern is that it can introduce a single point of failure and can in some cases become difficult to manage effectively.

    Consider modules as publishers and the mediator as both a publisher and subscriber. Module 1 broadcasts an event notifying the mediator something needs to done. The mediator captures this message and 'starts' the modules needed to complete this task Module 2 performs the task that Module 1 requires and broadcasts a completion event back to the mediator. In the mean time, Module 3 has also been started by the mediator and is logging results of any notifications passed back from the mediator.

    Notice how at no point do any of the modules directly communicate with one another. If Module 3 in the chain were to simply fail or stop functioning, the mediator could hypothetically 'pause' the tasks on the other modules, stop and restart Module 3 and then continue working with little to no impact on the system. This level of decoupling is one of the main strengths the pattern has to offer.

    To review, the advantages of the mediator are that:

    It decouples modules by introducing an intermediary as a central point of control.It allows modules to broadcast or listen for messages without being concerned with the rest of the system. Messages can be handled by any number of modules at once.

    It is typically significantly more easy to add or remove features to systems which are loosely coupled like this.

    And its disadvantages:

    By adding a mediator between modules, they must always communicate indirectly. This can cause a very minor performance drop - because of the nature of loose coupling, its difficult to establish how a system might react by only looking at the broadcasts. At the end of the day, tight coupling causes all kinds of headaches and this is one solution.

    Example: This is a possible implementation of the mediator pattern based on previous work by @rpflorence

    ```
    @@ -80,3 +64,9 @@ obj.subscribe('nameChange', function(arg){
    obj.publish('nameChange', 'john'); //sam, john
    ```

    The benefits of the Mediator pattern are that that it simplifies object interaction and can aid with decoupling those using it as a communication hub. Instead of using the Observer pattern to explicitly set many-to-many listeners and events, a Mediator allows you to broadcast events globally between subscribers and publishers. Broadcasted events can be handled by any number of modules at once and a mediator can used for a number of other purposes such as permissions management, given that it can control what messages can be subscribed to and which can be broadcast.

    Perhaps the biggest downside of using the Mediator pattern is that it can introduce a single point of failure and can in some cases become difficult to manage effectively. It's disadvantages also include that by adding a mediator between modules, they must always communicate indirectly. This can cause a very minor performance drop - because of the nature of loose coupling, its difficult to establish how a system might react by only looking at the broadcasts.

    At the end of the day, tight coupling causes all kinds of headaches and this is just another alternative solution, but one which can work very well if implemented correctly.
  5. addyosmani revised this gist Feb 15, 2012. 1 changed file with 3 additions and 7 deletions.
    10 changes: 3 additions & 7 deletions mediator.md
    Original file line number Diff line number Diff line change
    @@ -1,13 +1,10 @@
    The mediator pattern is best introduced with a simple analogy - think of your typical airport traffic control. The tower handles what planes can take off and land because all communications are done from the planes to the control tower, rather than from plane-to-plane. A centralized controller is key to the success of this system and that's really what a mediator is.

    Mediators are used when the communication between modules may be complex, but is still well defined. If it appears a system may have too many relationships between modules in your code, it may be time to have a central point of control, which is where the pattern fits in.
    In real-world terms, a mediator encapsulates how disparate modules interact with each other by acting as an intermediary. The pattern also promotes loose coupling by preventing objects from referring to each other explicitly - in our system, this helps to solve our module inter-dependency issues.
    Mediators are used when the communication between modules may be complex, but is still well defined. If it appears a system may have too many relationships between modules in your code, it may be time to have a central point of control, which is where the pattern fits in. In real-world terms, a mediator encapsulates how disparate modules interact with each other by acting as an intermediary. The pattern also promotes loose coupling by preventing objects from referring to each other explicitly - in our system, this helps to solve our module inter-dependency issues.

    What other advantages does it have to offer? Well, mediators allow for actions of each module to vary independently, so it’s extremely flexible. If you've previously used the Observer (Pub/Sub) pattern to implement an event broadcast system between the modules in your system, you'll find mediators relatively easy to understand.
    It's been described in the GoF book, Design Patterns: Elements of Reusable Object-Oriented Software as a behavioural pattern with the following goal: "Define an object that encapsulated how a set of objects interact. The Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently."

    Let's take a look at a high level view of how modules might interact with a mediator:

    <p class="illustration"><img src="assets/img/chart4a.jpg" width="618" height="297"></p>
    The benefits of this pattern are that that it simplifies object interaction and can aid with decoupling those using it as a communication hub. Instead of using the Observer pattern to explicitly set many-to-many listeners and events, a Mediator allows you to broadcast events globally between subscribers and publishers. Perhaps the biggest downside of using the Mediator pattern is that it can introduce a single point of failure and can in some cases become difficult to manage effectively.

    Consider modules as publishers and the mediator as both a publisher and subscriber. Module 1 broadcasts an event notifying the mediator something needs to done. The mediator captures this message and 'starts' the modules needed to complete this task Module 2 performs the task that Module 1 requires and broadcasts a completion event back to the mediator. In the mean time, Module 3 has also been started by the mediator and is logging results of any notifications passed back from the mediator.

    @@ -83,4 +80,3 @@ obj.subscribe('nameChange', function(arg){
    obj.publish('nameChange', 'john'); //sam, john
    ```

  6. addyosmani renamed this gist Feb 15, 2012. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  7. addyosmani revised this gist Feb 15, 2012. 1 changed file with 28 additions and 52 deletions.
    80 changes: 28 additions & 52 deletions mediator.html
    Original file line number Diff line number Diff line change
    @@ -1,45 +1,31 @@
    <div class="row">
    <p>
    <h3>The Mediator Pattern</h3><a name="mediatorpattern"></a>
    <p>
    The mediator pattern is best introduced with a simple analogy - think of your typical airport traffic control. The tower handles what planes can take off and land because all communications are done from the planes to the control tower, rather than from plane-to-plane. A centralized controller is key to the success of this system and that's really what a mediator is.</p>

    <div class="alert-message block-message warning">
    <p>
    Mediators are used when the communication between modules may be complex, but is still <b>well defined</b>. If it appears a system may have too many relationships between modules in your code, it may be time to have a central point of control, which is where the pattern fits in.</p></div>
    <p>
    In real-world terms, a mediator<strong> encapsulates</strong> how disparate modules <strong>interact</strong> with each other by acting as an intermediary. The pattern also promotes loose coupling by preventing objects from referring to each other explicitly - in our system, this helps to solve our module inter-dependency issues.</p>
    <p>
    The mediator pattern is best introduced with a simple analogy - think of your typical airport traffic control. The tower handles what planes can take off and land because all communications are done from the planes to the control tower, rather than from plane-to-plane. A centralized controller is key to the success of this system and that's really what a mediator is.

    Mediators are used when the communication between modules may be complex, but is still well defined. If it appears a system may have too many relationships between modules in your code, it may be time to have a central point of control, which is where the pattern fits in.
    In real-world terms, a mediator encapsulates how disparate modules interact with each other by acting as an intermediary. The pattern also promotes loose coupling by preventing objects from referring to each other explicitly - in our system, this helps to solve our module inter-dependency issues.

    What other advantages does it have to offer? Well, mediators allow for actions of each module to vary independently, so it’s extremely flexible. If you've previously used the Observer (Pub/Sub) pattern to implement an event broadcast system between the modules in your system, you'll find mediators relatively easy to understand.
    </p>
    <p>
    Let's take a look at a high level view of how modules might interact with a mediator:</p>

    Let's take a look at a high level view of how modules might interact with a mediator:

    <p class="illustration"><img src="assets/img/chart4a.jpg" width="618" height="297"></p>

    <p>
    Consider modules as publishers and the mediator as both a publisher and subscriber.
    Module 1 broadcasts an event notifying the mediator something needs to done.
    The mediator captures this message and 'starts' the modules needed to complete this task
    Module 2 performs the task that Module 1 requires and broadcasts a completion event back to the mediator. In the mean time, Module 3 has also been started by the mediator and is logging results of any notifications passed back from the mediator.</p>
    <p>
    Notice how at no point do any of the modules<strong> directly communicate</strong> with one another. If Module 3 in the chain were to simply fail or stop functioning, the mediator could hypothetically 'pause' the tasks on the other modules, stop and restart Module 3 and then continue working with little to no impact on the system. This level of decoupling is one of the main strengths the pattern has to offer. </p>
    <p>
    To review, the advantages of the mediator are that:</p>
    <p>
    It decouples modules by introducing an intermediary as a central point of control.It allows modules to broadcast or listen for messages without being concerned with the rest of the system. Messages can be handled by any number of modules at once. </p>
    <p>
    Consider modules as publishers and the mediator as both a publisher and subscriber. Module 1 broadcasts an event notifying the mediator something needs to done. The mediator captures this message and 'starts' the modules needed to complete this task Module 2 performs the task that Module 1 requires and broadcasts a completion event back to the mediator. In the mean time, Module 3 has also been started by the mediator and is logging results of any notifications passed back from the mediator.

    Notice how at no point do any of the modules directly communicate with one another. If Module 3 in the chain were to simply fail or stop functioning, the mediator could hypothetically 'pause' the tasks on the other modules, stop and restart Module 3 and then continue working with little to no impact on the system. This level of decoupling is one of the main strengths the pattern has to offer.

    To review, the advantages of the mediator are that:

    It decouples modules by introducing an intermediary as a central point of control.It allows modules to broadcast or listen for messages without being concerned with the rest of the system. Messages can be handled by any number of modules at once.

    It is typically significantly more easy to add or remove features to systems which are loosely coupled like this.
    </p>
    <p>

    And its disadvantages:
    </p>
    <p>
    By adding a mediator between modules, they must always communicate indirectly. This can cause a very minor performance drop - because of the nature of loose coupling, its difficult to establish how a system might react by only looking at the broadcasts. At the end of the day, tight coupling causes all kinds of headaches and this is one solution.</p>
    <p>
    <b>
    Example:</b> This is a possible implementation of the mediator pattern based on previous work by <a href="https://github.com/rpflorence">@rpflorence</a></p>
    <p>
    <pre class="prettyprint linenums">

    By adding a mediator between modules, they must always communicate indirectly. This can cause a very minor performance drop - because of the nature of loose coupling, its difficult to establish how a system might react by only looking at the broadcasts. At the end of the day, tight coupling causes all kinds of headaches and this is one solution.

    Example: This is a possible implementation of the mediator pattern based on previous work by @rpflorence

    ```
    var mediator = (function(){
    var subscribe = function(channel, fn){
    if (!mediator.channels[channel]) mediator.channels[channel] = [];
    @@ -68,15 +54,11 @@ <h3>The Mediator Pattern</h3><a name="mediatorpattern"></a>
    };

    }());
    </pre>
    </p>
    ```

    <p>
    <b>
    Example:</b> Here are two sample uses of the implementation from above. It's effectively managed publish/subscribe:
    Example: Here are two sample uses of the implementation from above. It's effectively managed publish/subscribe:

    <p>
    <pre class="prettyprint linenums">
    ```
    //Pub/sub on a centralized mediator

    mediator.name = "tim";
    @@ -100,11 +82,5 @@ <h3>The Mediator Pattern</h3><a name="mediatorpattern"></a>
    });

    obj.publish('nameChange', 'john'); //sam, john
    </pre>
    </p>
    <div class="alert-message block-message info">
    <p><strong>Related Reading</strong>
    <p>Stoyan Stefanov - Page 168, JavaScript Patterns<br>
    <a href="http://arguments.callee.info/2009/05/18/javascript-design-patterns--mediator/">HB Stone - JavaScript Design Patterns: Mediator</a><br>
    <a href="http://www.vincehuston.org/dp/mediator.html">Vince Huston - The Mediator Pattern (not specific to JavaScript, but a concise)</a></p></p></div>
    <p>&nbsp;</p>
    ```

  8. addyosmani created this gist Feb 15, 2012.
    110 changes: 110 additions & 0 deletions mediator.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,110 @@
    <div class="row">
    <p>
    <h3>The Mediator Pattern</h3><a name="mediatorpattern"></a>
    <p>
    The mediator pattern is best introduced with a simple analogy - think of your typical airport traffic control. The tower handles what planes can take off and land because all communications are done from the planes to the control tower, rather than from plane-to-plane. A centralized controller is key to the success of this system and that's really what a mediator is.</p>

    <div class="alert-message block-message warning">
    <p>
    Mediators are used when the communication between modules may be complex, but is still <b>well defined</b>. If it appears a system may have too many relationships between modules in your code, it may be time to have a central point of control, which is where the pattern fits in.</p></div>
    <p>
    In real-world terms, a mediator<strong> encapsulates</strong> how disparate modules <strong>interact</strong> with each other by acting as an intermediary. The pattern also promotes loose coupling by preventing objects from referring to each other explicitly - in our system, this helps to solve our module inter-dependency issues.</p>
    <p>
    What other advantages does it have to offer? Well, mediators allow for actions of each module to vary independently, so it’s extremely flexible. If you've previously used the Observer (Pub/Sub) pattern to implement an event broadcast system between the modules in your system, you'll find mediators relatively easy to understand.
    </p>
    <p>
    Let's take a look at a high level view of how modules might interact with a mediator:</p>
    <p class="illustration"><img src="assets/img/chart4a.jpg" width="618" height="297"></p>

    <p>
    Consider modules as publishers and the mediator as both a publisher and subscriber.
    Module 1 broadcasts an event notifying the mediator something needs to done.
    The mediator captures this message and 'starts' the modules needed to complete this task
    Module 2 performs the task that Module 1 requires and broadcasts a completion event back to the mediator. In the mean time, Module 3 has also been started by the mediator and is logging results of any notifications passed back from the mediator.</p>
    <p>
    Notice how at no point do any of the modules<strong> directly communicate</strong> with one another. If Module 3 in the chain were to simply fail or stop functioning, the mediator could hypothetically 'pause' the tasks on the other modules, stop and restart Module 3 and then continue working with little to no impact on the system. This level of decoupling is one of the main strengths the pattern has to offer. </p>
    <p>
    To review, the advantages of the mediator are that:</p>
    <p>
    It decouples modules by introducing an intermediary as a central point of control.It allows modules to broadcast or listen for messages without being concerned with the rest of the system. Messages can be handled by any number of modules at once. </p>
    <p>
    It is typically significantly more easy to add or remove features to systems which are loosely coupled like this.
    </p>
    <p>
    And its disadvantages:
    </p>
    <p>
    By adding a mediator between modules, they must always communicate indirectly. This can cause a very minor performance drop - because of the nature of loose coupling, its difficult to establish how a system might react by only looking at the broadcasts. At the end of the day, tight coupling causes all kinds of headaches and this is one solution.</p>
    <p>
    <b>
    Example:</b> This is a possible implementation of the mediator pattern based on previous work by <a href="https://github.com/rpflorence">@rpflorence</a></p>
    <p>
    <pre class="prettyprint linenums">
    var mediator = (function(){
    var subscribe = function(channel, fn){
    if (!mediator.channels[channel]) mediator.channels[channel] = [];
    mediator.channels[channel].push({ context: this, callback: fn });
    return this;
    },

    publish = function(channel){
    if (!mediator.channels[channel]) return false;
    var args = Array.prototype.slice.call(arguments, 1);
    for (var i = 0, l = mediator.channels[channel].length; i < l; i++) {
    var subscription = mediator.channels[channel][i];
    subscription.callback.apply(subscription.context, args);
    }
    return this;
    };

    return {
    channels: {},
    publish: publish,
    subscribe: subscribe,
    installTo: function(obj){
    obj.subscribe = subscribe;
    obj.publish = publish;
    }
    };

    }());
    </pre>
    </p>

    <p>
    <b>
    Example:</b> Here are two sample uses of the implementation from above. It's effectively managed publish/subscribe:

    <p>
    <pre class="prettyprint linenums">
    //Pub/sub on a centralized mediator

    mediator.name = "tim";
    mediator.subscribe('nameChange', function(arg){
    console.log(this.name);
    this.name = arg;
    console.log(this.name);
    });

    mediator.publish('nameChange', 'david'); //tim, david


    //Pub/sub via third party mediator

    var obj = { name: 'sam' };
    mediator.installTo(obj);
    obj.subscribe('nameChange', function(arg){
    console.log(this.name);
    this.name = arg;
    console.log(this.name);
    });

    obj.publish('nameChange', 'john'); //sam, john
    </pre>
    </p>
    <div class="alert-message block-message info">
    <p><strong>Related Reading</strong>
    <p>Stoyan Stefanov - Page 168, JavaScript Patterns<br>
    <a href="http://arguments.callee.info/2009/05/18/javascript-design-patterns--mediator/">HB Stone - JavaScript Design Patterns: Mediator</a><br>
    <a href="http://www.vincehuston.org/dp/mediator.html">Vince Huston - The Mediator Pattern (not specific to JavaScript, but a concise)</a></p></p></div>
    <p>&nbsp;</p>