You are on page 1of 4

Observer Design Pattern

Page 1 sur 4

Observer pattern
Origin
This Observer pattern is based on the Observer pattern as described in [Gam+, pages
293..303]. The implementation in Delphis Object Pascal language originates from
White Ants.

Intent
Define a one-to-many dependency between objects so that when one object changes
state, all its dependants are notified and updated automatically [Gam+, p293]

Motivation
A common side-effect of partitioning a system into a collection of co-operating
classes, is the need to maintain consistency between related objects. You dont want to
achieve consistency by making the classes tightly coupled, because that reduces their
reusability [Gam+, p293].
Delphis events (which are actually method pointers) let you deal with this problem in
a structured manner. Events let you decouple classes that need to co-operate. For
example: The TButton.OnClick event is dispatched to whom it may concern, the
button does not store a (typed) reference to the class handling the event. In fact the
event might not even be handled at all. In terms of the observer pattern the object
dispatching an event is called subject, the object handling the event is called observer.
So Delphis events take care of decoupling classes, but what if you want to handle an
event in more than one place? An observer pattern describes how to establish one-tomany notifications. A subject may have any number of observers. All observers are
notified whenever the subject undergoes a change in state (such as a button being
clicked). In response each observer may query the subject to synchronise its state with
the subjects state [Gam+, p 294].
This kind of interaction is also known as publish-subscribe, the subject is the
publisher of notifications. It sends out these notifications without having to know who
its observers are. Any number of observers can subscribe to receive
notifications [Gam+, p 294].

Implementation
The implementation of the observer pattern is taking advantage of Delphis events to
deal with decoupling classes. The one-to-many aspect is implemented by registering

http://www.castle-cadenza.demon.co.uk/observe.htm

04/12/2007

Observer Design Pattern

Page 2 sur 4

and un-registering dedicated observers. The one-to-many mechanism is actually


implemented by iterating over the list of observers.
Lets assume youve got a class TSubject which defines useful behaviour. The
following code demonstrates the implementation of the observer pattern.
type
TSubject = class (TObject)
private
FObservers: TList;
public
procedure RegisterObserver(Observer: TSubjectObserver);
procedure UnregisterObserver(Observer: TSubjectObserver);
end;
TSubjectObserver = class (TComponent)
private
FEnabled: Boolean;
published
property Enabled: Boolean read FEnabled write FEnabled; default
True;
end;

In this interface: A registration mechanism has been added to the class TSubject,
consisting of: FObservers: TList; which stores all registered observers.
RegisterObserver(..), which registers an observer by adding it to FObservers.
UnregisterObserver(..), which unregisters an observer by removing it from
FObservers. A new class Observer patternhas been created: TSubjectObserver This
class is a TComponent descendant. It has an Enabled property which allows you to
switch the observer on and off rather than having to register / unregister it each time.
How this property actually cooperates in the one-to-many event dispatch mechanism
will be explained shortly.
The actual implementation of this pattern is:
procedure TSubject.RegisterObserver(Observer: TSubjectObserver);
begin
if FObservers.IndexOf(Observer) = -1 then
FObservers.Add(Observer);
end;
procedure TSubject.UnregisterObserver(Observer: TSubjectObserver);
begin
FObservers.Remove(Observer);
end;

As you see in the implementation: this deals only with the registration part of the

http://www.castle-cadenza.demon.co.uk/observe.htm

04/12/2007

Observer Design Pattern

Page 3 sur 4

observer pattern. Now you may ask: where is my one-to-many notification?. Well:
its not possible to implement this as part of the pattern. The actual one-to-many
notifications you have to implement yourself. Assume that TSubject has a method
Change which notifies all its registered observers of a change. The observers would
have an OnChange event property which is actually dispatched. You could implement
this like:
type
TSubject = class (TObject)
private
FObservers: TList;
protected
procedure Change;
{ Call this method to dispatch change }
public
procedure RegisterObserver(Observer: TSubjectObserver);
procedure UnregisterObserver(Observer: TSubjectObserver);
end;
TSubjectObserver = class (TComponent)
private
FEnabled: Boolean;
FOnChange: TNotifyEvent;
protected
procedure Change;
published
property Enabled: Boolean read FEnabled write FEnabled;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
end;
implementation
procedure TSubject.Change;
var
Obs: TSubjectObserver;
I: Integer;
begin
for I := 0 to FObservers.Count - 1 do
begin
Obs := FObservers[I];
if Obs.Enabled then Obs.Change;
end;
end;
procedure TSubject.RegisterObserver(Observer: TSubjectObserver);
begin
if FObservers.IndexOf(Observer) = -1 then

http://www.castle-cadenza.demon.co.uk/observe.htm

04/12/2007

Observer Design Pattern

Page 4 sur 4

FObservers.Add(Observer);
end;
procedure TSubject.UnregisterObserver(Observer: TSubjectObserver);
begin
FObservers.Remove(Observer);
end;
procedure TSubjectObserver.Change;
begin
if Assigned(FOnChange) then FOnChange(Self);
end;

In this example notice: the method TSubject.Change which iterates the registered
observers, calling each observers Change method. This is the actual one-to-many
notification. the observers Enabled property which is checked to determine whether
the observer should be notified; the event OnChange in the class TSubjectObserver
which can be wired using the object inspector.

http://www.castle-cadenza.demon.co.uk/observe.htm

04/12/2007

You might also like