Thursday, November 8, 2012

Mediator Design Pattern

Although they are lots of books and articles about Design Patterns, yet I like to share my point of view about common design patterns with you, and would be happy to have your thoughts or questions on comments. This post introduces GoF Mediator design pattern.

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. (dofactory)

  • Mediator defines an interface for communicating with Colleague objects.
  • ConcreteMediator implements cooperative behavior by coordinating Colleague objects; also ConcreteMediator  knows and maintains its colleagues.
  • Colleague knows its Mediator object and communicates with its mediator whenever it would have otherwise communicated with another colleague.

  • There is no need to create an Abstract Mediator class or an interface as long as the colleagues are going to use only one mediator. The definition of an abstract Mediator is required only if the colleagues needs to work with different mediators.
  • An airport control tower is an excellent example of the mediator pattern. The tower looks after who can take off and land - all communications are done from the airplane to control tower, rather than having plane-to-plane communication. This idea of a central controller is one of the key aspects to the mediator pattern.

  •  Design an intermediary to decouple many peers. An example is a Chatroom which is the central hub through which all communication takes place.
  • Promote the many-to-many relationships between interacting peers to “full object status”.
  • A set of objects communicate in well-defined but complex ways. The resulting interdependencies are unstructured and difficult to understand.
  • Reusing an object is difficult because it refers to and communicates with many other objects.
  • A behavior that's distributed between several classes should be customizable without a lot of subclassing.
  • GUI framework: Classes representing forms (Dialog, Form,... ) represents the the mediator while each control represents a colleague. The form class provides the mechanism to facilitate the interaction between controls; an inherited class is created each time a new screen is created and the specific code is written in this class. This way, the controls communication is mediated by this form class.
  • The mediator is especially useful in projects are built around the MVVM pattern, because it enables communication between separate and unrelated ViewModels, which may reside in different parts of the application (like separate windows), or from deep within autogenerated controls (like in cells of DataGrid). 
  • The Java Message Service (JMS) API is a Java Message Oriented Middleware (MOM) API for sending messages between two or more clients. The JMS API supports 2 models. One of them is the publish-subscribe model. It is an implementation of the mediator pattern. The messages can be publisehd based on a particular topic. The publisher has to create a subscription to which different subscribers may subscribe. Zero or more subscribers may subscribe to receive messages on a particular message topic. The publisher and the subscriber doesn't know one about each other, the subscriber can be even inactive. In this case the subscriber receives the messages when it will become active.
  • The mediator is a central hub through which all interaction must take place.
  • The mediator encapsulate the logic of mediation between the colleagues. From this reason it is more easier to understand this logic since it is kept in only one class. Because the entire communication logic is encapsulated by the mediator class, when this logic need to be extended only the mediator class need to be extended.
  • The colleague classes are totally decoupled. Adding a new colleague class is very easy due to this decoupling level.
  • The colleague objects need to communicate only with the mediator objects. Practically the mediator pattern reduce the required communication channels(protocols) from many to many to one to many and many to one.
  • When the number of participants is a high and the different participant classes is high, In practice the mediators tends to become more complex and complex. So, Be careful not to create a “controller” or “god” object.  A good practice is to take care to make the mediator classes responsible only for the communication part. For example when implementing different screens the the screen class should not contain code which is not a part of the screen operations. It should be put in some other classes.

Sample Code

Related Patterns
  • Chain of Responsibility, Command, Mediator, and Observer, address how you can decouple senders and receivers, but with different trade-offs. Chain of Responsibility passes a sender request along a chain of potential receivers. Command normally specifies a sender-receiver connection with a subclass. Mediator has senders and receivers reference each other indirectly. Observer defines a very decoupled interface that allows for multiple receivers to be configured at run-time.
  • Mediator and Observer are competing patterns. The difference between them is that Observer distributes communication by introducing “observer” and “subject” objects, whereas a Mediator object encapsulates the communication between other objects. We have found it easier to make reusable Observers and Subjects than to make reusable Mediators. On the other hand, Mediator can leverage Observer for dynamically registering colleagues and communicating with them.
  • Mediator is similar to Facade in that it abstracts functionality of existing classes. Mediator abstracts/centralizes arbitrary communication between colleague objects, it routinely “adds value”, and it is known/referenced by the colleague objects (i.e. it defines a multidirectional protocol). In contrast, Facade defines a simpler interface to a subsystem, it does not add new functionality, and it is not known by the subsystem classes (i.e. it defines a unidirectional protocol where it makes requests of the subsystem classes but not vice versa).

Futher readings

No comments :

Post a Comment