ghytred.com


NewsLook for Outlook

Patterns and OO
MediatorPattern
The Web Site you seek
Cannot be located, so
Waste your time here

Contents

Mediator

From GoF 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 allows you to vary

I find this diagram less than helpful.

A concrete example of Mediator:

[svs: Forgive the complex description; but that's when you use Mediator...]

I did a system a few years ago whose purpose was to administer a gas pipeline, called the SILK pipeline which flowed gas between two other pipelines: from the SEAL pipeline to the Interconnector. There were a number of 'Shippers' who could put gas through the pipeline. They got the gas from a number of other shippers (SEAL shippers). Each SILK shipper could get gas from one or more of them. Each SILK shipper informed the SEAL pipeline operator which SEAL Shipper was going to supply them and with how much. (They did this on a daily basis, specifying for each day how much each hour would be supplied, but that's not really relevant.) This notification was called a Nomination. Similarly, the SEAL Shipper nominated to the SEAL operator how much they were going to supply to each SILK Shipper.

At the other end of the pipeline the same thing happened. The Shippers nominated to the Interconnector operator how much gas they were going to deliver to and to whom (Interconnector shippers). The Interconnector shippers also nominated to the Interconnector operator how much gas they were going to receive and from whom.

All these nominations were copied to the SILK operator, the user of this system.

At the end of the day, the SEAL pipeline operator worked out how much gas had actually been entered into the SILK pipeline and told the SILK operator. The Interconnector also told the SILK operator how much gas had come out. The SILK operator now had to allocate this gas to the individual Shippers, specifying how much of the input was credited to them � and from which SEAL Shipper it was received � and how much of the output, and to which Interconnector shipper it had gone.

These calculations were horrendously complex and depended on whether the nomination from the SEAL shipper matched that from the SILK Shipper (and similarly at the Interconnector end), whether there was a nomination from both but the figure didn't match, or whether there was a nomination from one but not the other. There were a number of objects involved � SEAL Shipper to SILK Shipper, SILK from SEAL, SILK to Interconnector, Interconnector from SILK (and all the hourly breakdowns). The logic for this matching process did not belong in any of these objects.

The solution was to create a new object: AllocationMediator. This knew about all these other objects and had the complex matching logic. It had no permanent data, who had said what was going to happen and the totals that had actually happened, and the rules for allocating those totals.

Relating this system to the diagram, there was only one mediator thus there was no need for an abstract and concrete class, just a concrete class. There were actually 9 colleagues � 4 Nomination types as input, 4 allocation types as output (the SEAL allocation types were also inputs to the allocation at the Interconnector end), and a Silk Shipper Balance type also as output.

This design allowed the 9 colleagues to exist without knowing about any of the others. Thus when one changed all that had to change was the AllocationMediator and not the other 8.

This was in one way a 'simple' Mediator: the Colleague classes did not know about it (see the last point from GoF below). I still call it a Mediator because of the complexity and number of rules it encapsulated; a facade seems to me to be far more lightweight than this object was and also a facade should totally encapsulate the colleagues, which this did not. Another example of similarity in patterns: 'Is it a mediator? Is it a Facade? Who cares, it works!'.

Another often-quoted example of a Mediator is an object which connects participants in a chat-room with each other.

Finally, if the logic in a mediator is switchable, consider using a Strategy pattern to provide the differing logic code if possible. If not, you may need an abstract and a number of Concrete Mediators. If this in turn isn't possible, try to break down the Mediator into simpler mediators controlled by the main one (this could have been done in the pipeline example above).

Points from GoF:

  • Chain of Responsibility, Command, Mediator, and Observer, address how you can decouple senders and receivers, but with different trade-offs. A 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. [GOF, p347]
  • 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've found it easier to make reusable Observers and Subjects than to make reusable Mediators. [GOF, p346]
  • On the other hand, Mediator can leverage Observer for dynamically registering colleagues and communicating with them. [GOF, p282]
  • 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 doesn't 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). [GOF, p193]

From CodePro Java Patterns:

Use the Mediator pattern when

  • a set of objects communicate in well-defined but complex ways. The resulting interdependencies are 'unstructured' and difficult to understand.
  • re-using or changing an object is difficult because it refers to and communicates with many other objects.
  • a behaviour that's distributed between several classes should be customizable without a lot of subclassing.

Various comments from around the Web:

  • Typically reduces the number of subclasses of colleague classes
  • Reduces / loosens the bindings between colleague classes � the relationships are moved to the mediator class(es)
  • Simplifies object relationships � many-to-many relationships are reduced to simpler unidirectional associations
  • Complex interaction protocols are encapsulated by a single (ConcreteMediator) object, simplifying the resulting design
  • Mediators may tend to become hard-to-maintain or enhanced �god� objects if given too much centralized control
  • The Mediator pattern uses the Interface pattern to keep the Colleague classes independent of the Mediator class. (This is good advice for when the Colleagues need to know about the Mediator: let them know about an Interface the mediator implements rather than the mediator itself.)
  • Omitting the abstract Mediator class:
    • The abstract coupling that the Mediator class provides lets colleagues work with different Mediator subclasses, and vice versa.
    • When colleagues work with only one type of Mediator, you don't need to define an abstract Mediator class.
  • Colleague-Mediator communication:
    • Colleagues communicate with their mediator when an event of interest occurs.
    • One approach is to implement the Mediator as an Observer using the Observer pattern.
      • Colleagues act as subjects notifying the mediator whenever they change state.
      • The mediator responds by propagating the effects of the change to other colleagues.

Return to top