1. Home
  2. Computing & Technology
  3. Delphi Programming

Indirection - Delphi OOP Part 8 - Chapter 18

By Zarko Gajic, About.com

In this new version we finally have the required encapsulation. The references in the code above are only to a TMuseumCount object, not to any TCounter objects.

The user interface class no longer has any involvement with the application logic, and the user interface can perform only those operations made available by TMuseumCount.

These are the conceptual operations of so many entered and so many left. It is not affected in any way by how the application object MuseumCount manipulates these values and the programmer does not have to remember that a visitor entering the museum involves incrementing two counts.

As these examples show, delegation involves more coding than chaining. For example, using chaining (example 8.2 step 1) TMuseumCount needs 21 lines of code. Using delegation (example 8.3 step 1), it needs 56 lines of (quite simple and mechanical) code. Offset against this cost of delegation is the gain in encapsulation with the resulting improved robustness.

We again illustrate the With … Do construct as an alternative for identifying the object to which the message is sent. While it may save typing, some programmers feel that the With … Do construct can be misleading and a source of error. For example, it’s not immediately clear whether the parameter Left refers to MuseumCount.Left or frmAttendance.Left.

Ex 8.3 step 3 Encapsulated changes

To emphasise the benefits of encapsulation, let’s reconsider the TMuseum class. At the moment, it uses three counters. But we can also solve this problem by using only two: one for Entered and one for Left. From these two we can calculate the count for Inside.

If we make these changes in the programs of either example 8.1 (interfacing directly with the counters) or example 8.2 (using chaining through an intermediate object) we have to make significant changes to the user interface class, TfrmAttendance.

Using delegation, we don’t need to change either the user interface class or the TCounter class – we can keep all the changes hidden within the private sections of TMuseumCount.

unit MuseumCountU;

// using delegation, but with only two counters

interface

uses CounterU;

type
   TMuseumCount = class(TObject)
   private
     VEntered, VLeft: TCounter; // now only two counters
     function GetEntered: integer;
     function GetInside: integer;
     function GetLeft: integer;
   public
     // but 3 read-only, method mapped properties using delegation
     property Entered: integer read GetEntered;
     property Inside: integer read GetInside;
     property Left: integer read GetLeft;
     procedure Arrivals (aNumber: integer) ;
     procedure Departures (aNumber: integer) ;
     procedure ClearAll;
     constructor Create;
   end;

implementation

procedure TMuseumCount.Arrivals(aNumber: integer) ;
begin
   VEntered.Add (aNumber) ;
end;

procedure TMuseumCount.Departures(aNumber: integer) ;
begin
   VLeft.Add (aNumber) ;
end;

function TMuseumCount.GetEntered: integer;
begin
   Result := VEntered.Total;
end;

function TMuseumCount.GetInside: integer;
begin
   Result := VEntered.Total - VLeft.Total;
end;

function TMuseumCount.GetLeft: integer;
begin
   Result := VLeft.Total;
end;

procedure TMuseumCount.ClearAll;
begin
   VEntered.Clear;
   VLeft.Clear;
end;

constructor TMuseumCount.Create;
begin
   inherited Create;
   VEntered := TCounter.Create;
   VLeft := TCounter.Create;
end;

end.
We introduced an intermediate object that now meets its responsibility for carrying out the application logic by delegating operations to worker objects.

It is unaware that the intermediate object actually delegates some of its work to other objects. Because delegation allows the program to comply with the ‘neighbours only’ principle, whether and how the intermediate object delegates totalling the counts to other objects or even whether it does this itself does not affect the user interface.

Since the user interface object now communicates with only the single intermediate object, rather than with three counter objects, its coupling with the rest of the system is reduced. In general it is good to reduce coupling where feasible.

Introducing delegation into this program has been very useful, and we have been able to:

  • separate and distribute responsibilities appropriately between different objects (user interface, application logic, workers),
  • avoid excessive coupling, and
  • comply with the ‘neighbours only’ principle.
As we saw in example 8.2, using chaining instead of delegation violates these principles.
Zarko Gajic
Guide since 1998

Zarko Gajic
Delphi Programming Guide

Explore Delphi Programming
About.com Special Features

Stay connected and entertained with reviews on tips on the latest HDTVs, cellphones and more. More >

Easy ways to connect two computers for networking purposes. More >

  1. Home
  2. Computing & Technology
  3. Delphi Programming
  4. Coding Delphi Applications
  5. OOP in Delphi
  6. Free Online OOP Course
  7. Indirection - Delphi OOP Part 8 - Chapter 18

©2009 About.com, a part of The New York Times Company.

All rights reserved.