You are on page 1of 5

Mediator Design Pattern Page 1 sur 5

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.

Though partitioning a system into many objects generally enhances reusability,


proliferating interconnections tend to reduce it again. Lots of interconnections make it
less likely that an object can work without the support of others - the system acts as
though it were monolithic. Moreover it can be difficult to change the systems'
behaviour in any significant way, since behaviour is distributed among many objects.
As a result, you may be forced to define many subclasses to customise the system's
behaviour.' [Gam+ page 273].

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.

This TController class would typically


wire and handle the Comport events to
update it’s internal state. Here’s an
abstract of the interface and implementation of TComport and TController without the
mediator:

type
TLineEvent = procedure (Sender: TObject; Error: TLineError) of
object;
TTriggerEvent = procedure (Sender: TObject; Trigger: TTrigger) of
object;

TComPort = class (TObject)


published
property OnDataReceived: TTriggerEvent read FOnDataReceived
write FOnDataReceived;
property OnLineEvent: TLineEvent read FOnLineEvent write
FOnLineEvent;
property OnTimeOut: TNotifyEvent read FOnTimeOut write
FOnTimeOut;
property OnTransmitted: TNotifyEvent read FOnTransmitted
write
FOnTransmitted;
end;

http://www.castle-cadenza.demon.co.uk/mediat.htm 04/12/2007
Mediator Design Pattern Page 3 sur 5

TController = class (TObject)


private
FComPort: TComPort;
public
constructor Create;
destructor Destroy; override;
property ComPort: TComPort read FComPort;
end;

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:

TController = class (TObject)


private
FComPort: TComPort;
protected
procedure ComPortDataReceived(Sender: TObject; Trigger:
TTrigger);
procedure ComPortLineEvent(Sender: TObject; Error: TLineError);
procedure ComPortTimeOut(Sender: TObject);
procedure ComPortTransmitted(Sender: TObject);
procedure UnwireComPort;
procedure WireComPort;
public
constructor Create;
destructor Destroy; override;
property ComPort: TComPort read FComPort;
end;

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.ComPortDataReceived(Sender: TObject; Trigger:


TTrigger);
begin
end;

procedure TController.ComPortLineEvent(Sender: TObject; Error:


TLineError);
begin
end;

procedure TController.ComPortTimeOut(Sender: TObject);


begin
end;

procedure TController.ComPortTransmitted(Sender: TObject);


begin
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

You might also like