Wednesday, February 9, 2011

Behavioral Patterns - Mediator Pattern

Definition

Define an object that encapsulates details and other objects interact with such object. The relationships are loosely decoupled.


Intent

  • Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.
  • Design an intermediary to decouple many peers.
  • Promote the many-to-many relationships between interacting peers to “full object status”.

Problem

We want to design reusable components, but dependencies between the potentially reusable pieces demonstrates the “spaghetti code” phenomenon (trying to scoop a single serving results in an “all or nothing clump”).

Where to use & benefits

  • Partition a system into pieces or small objects.
  • Centralize control to manipulate participating objects(a.k.a colleagues)
  • Clarify the complex relationship by providing a board committee.
  • Limit subclasses.
  • Improve objects reusabilities.
  • Simplify object protocols.
  • The relationship between the control class and other participating classes is multidirectional.
  • Related patterns include
    • Facade, which abstracts a subsystem to provide a more convenient interface, and its protocol is unidirectional, whereas a mediator enables cooperative behavior and its protocol is multidirectional.
    • Command, which is used to coordinate functionality.
    • Observer, which is used in mediator pattern to enhance communication. 


     

    Structure

    Mediator scheme

    Colleagues (or peers) are not coupled to one another. Each talks to the Mediator, which in turn knows and conducts the orchestration of the others. The “many to many” mapping between colleagues that would otherwise exist, has been “promoted to full object status”. This new abstraction provides a locus of indirection where additional leverage can be hosted.

    Mediator scheme
     

     

    Motivation

    In order to have a good object oriented design we have to create lots of classes interacting one with each other. If certain principles are not applied the final framework will end in a total mess where each object relies on many other objects in order to run. In order to avoid tight coupled frameworks, we need a mechanism to facilitate the interaction between objects in a manner in that objects are not aware of the existence of other objects.
    Let's take the example of a screen. When we create it we add all sort of controls to the screen. This control need to interact with all the other control. For example when a button is pressed it must know if the data is valid in other controls. As you have seen if you created different applications using forms you don't have to modify each control class each time you add a new control to the form. All the operations between controls are managed by the form class itself. This class is called mediator.

    Intent

    Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.













    Mediator Implementation - UML Class Diagram



    Mediator in Java

    Why read if you can watch?

    Watch design patterns video tutorial
    Read full article

    Mediator design pattern

    1. Create an “intermediary” that decouples “senders” from “receivers”
    2. Producers are coupled only to the Mediator
    3. Consumers are coupled only to the Mediator
    4. The Mediator arbitrates the storing and retrieving of messages
    // 1. The "intermediary"
    class Mediator {
      // 4. The Mediator arbitrates
      private boolean slotFull = false;
      private int number;
      public synchronized void storeMessage( int num ) {
        // no room for another message
        while (slotFull == true) {
          try {
            wait();
          }
          catch (InterruptedException e ) { }
        }
        slotFull = true;
        number = num;
        notifyAll();
      }
      public synchronized int retrieveMessage() {
        // no message to retrieve
        while (slotFull == false)
          try {
            wait();
          }
          catch (InterruptedException e ) { }
        slotFull = false;
        notifyAll();
        return number;
      }
    }
    
    class Producer extends Thread {
      // 2. Producers are coupled only to the Mediator
      private Mediator med;
      private int    id;
      private static int num = 1;
      public Producer( Mediator m ) {
        med = m;
        id = num++;
      }
      public void run() {
        int num;
        while (true) {
          med.storeMessage( num = (int)(Math.random()*100) );
          System.out.print( "p" + id + "-" + num + "  " );
        }
      }
    }
    
    class Consumer extends Thread {
      // 3. Consumers are coupled only to the Mediator
      private Mediator med;
      private int    id;
      private static int num = 1;
      public Consumer( Mediator m ) {
        med = m;
        id = num++;
      }
      public void run() {
        while (true) {
          System.out.print("c" + id + "-" + med.retrieveMessage() + "  ");
        }
      }
    }
    
    class MediatorDemo {
      public static void main( String[] args ) {
        Mediator mb = new Mediator();
        new Producer( mb ).start();
        new Producer( mb ).start();
        new Consumer( mb ).start();
        new Consumer( mb ).start();
        new Consumer( mb ).start();
        new Consumer( mb ).start();
      }
    }
    p1-87 c1-87 p2-37 c3-37 p1-28 c2-28 p2-58 c1-58 p1-18 c4-18 p2-42 c3-42 p1-3 c2-3 p2-11 c3-11 p1-72 c2-72 p2-75 c3-75 p1-93 c4-93 p2-52 c1-52 p1-21 c3-21 p2-80 c4-80 p1-96 c2-96

No comments:

Post a Comment