Professional Documents
Culture Documents
Mediator pattern
Origin
This Mediator pattern is based on the Mediator pattern as described in [Gam+, pages
273..282].
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'. [Gam+, page 273]
Motivation
'Object oriented design encourages the distribution of behaviour among objects. Such
distribution can result in an object structure with many connections between objects;
in the worst case, every object ends up knowing about every other.
Although there's a lot more to tell about mediators, we won't get into details here,
please refer to [Gam+]. That's not because you don't need mediators, but because you
already are familiar with them: Delphi provides great mediators.
Developers at Borland probably were aware of the above mentioned paragraphs when
designing the Delphi Object Pascal language and the VCL components. Their solution
to this problem is essentially: events (or method pointers). The use of events makes
de-coupling of objects possible. The class TForm is their standard mediator class
which handles (wires) events from components put on the form. They even delivered a
great tool with it: the Object Inspector. Being able to delegate behaviour to another
class using events, saves you, for example, from subclassing TButton when you need
a button that interacts with an TEdit control. The mediator is the form which handles
all events and takes corresponding actions, coupling all related components together
with snippets of code. Great. So what's the need for a Mediator pattern?
Delphi's Object Inspector uses RTTI and form designers to create event handlers on
http://www.castle-cadenza.demon.co.uk/mediat.htm 04/12/2007
Mediator Design Pattern Page 2 sur 5
forms and Delphi's component streaming mechanism takes care of actually wiring
these events at run time.
If you ever manually created event handlers you know that you have to:
Create a event handler method with the correct parameter list and possibly the correct
function result. Wire the event handler to the event with code like:
FSample.OnChange := SampleChange;
Make sure you unwire the event again in appropriate cases to avoid wired objects
from calling destroyed or otherwise illegal objects.
In order to construct a correct event handler method it needs the event type definition.
The mediator pattern relies on these event type definitions to construct and update
event handlers.
Implementation
Suppose we've created a class TComPort which encapsulates a serial port device
driver. This class defines a series of events to asynchronously inform clients of state
changes: data triggers, line errors etc. A TController class could 'use a' TComPort
class to transmit data through a serial port.
type
TLineEvent = procedure (Sender: TObject; Error: TLineError) of
object;
TTriggerEvent = procedure (Sender: TObject; Trigger: TTrigger) of
object;
http://www.castle-cadenza.demon.co.uk/mediat.htm 04/12/2007
Mediator Design Pattern Page 3 sur 5
implementation
constructor TController.Create;
begin
inherited Create;
FComPort := TComPort.Create;
end;
destructor TController.Destroy;
begin
FComPort.Free;
inherited Destroy;
end;
Now have a look at the same abstract for class TController with the mediator applied
to this structure:
implementation
constructor TController.Create;
http://www.castle-cadenza.demon.co.uk/mediat.htm 04/12/2007
Mediator Design Pattern Page 4 sur 5
begin
inherited Create;
FComPort := TComPort.Create;
{ now wire comport calling the method created by the mediator }
WireComport;
end;
destructor TController.Destroy;
begin
{ make sure the comport is unwired again }
UnwireComport;
FComPort.Free;
inherited Destroy;
end;
procedure TController.UnwireComPort;
begin
FComPort.OnDataReceived := nil;
FComPort.OnLineEvent := nil;
FComPort.OnTimeOut := nil;
FComPort.OnTransmitted := nil;
end;
procedure TController.WireComPort;
begin
FComPort.OnDataReceived := ComPortDataReceived;
FComPort.OnLineEvent := ComPortLineEvent;
FComPort.OnTimeOut := ComPortTimeOut;
http://www.castle-cadenza.demon.co.uk/mediat.htm 04/12/2007
Mediator Design Pattern Page 5 sur 5
FComPort.OnTransmitted := ComPortTransmitted;
end;
In this example notice: The wiring of the comport in constructor Create by a call to
WireComPort. This method is optionally created by the mediator. The corresponding
unwiring in destructor Destroy by a call to UnwireComPort. This method is optionally
created by the mediator. The event handler methods which all have the correct
signature (as defined in the event library), just like the Object Inspector would do.
http://www.castle-cadenza.demon.co.uk/mediat.htm 04/12/2007