castle-cadenza - Builder pattern.pdf

Embed Size (px)

DESCRIPTION

This builder pattern is based on that described in [Gam+, pages 97..106]. The Delphi implementation for the pattern is from Shaun Parry

Citation preview

  • Builder pattern

    Origin This builder pattern is based on that described in [Gam+, pages 97..106]. The Delphi implementation for the pattern is from Shaun Parry.

    Intent 'Define an interface for creating an object, but let subclasses decide which class to instantiate' [Gam+,p97].

    Motivation The motivation is based on [Gam+, page 97]. Builder has a similar motivation to the abstract factory but, whereas in that pattern, the client uses the abstract factory class methods to create its own object, in Builder the client instructs the builder class on how to create the object and then asks it for the result. How the class is put together is up to the Builder class. It's a subtle difference.

    Implementation The following is an example of making a panel with three edit boxes within it, as with the Abstract Factory pattern. Again we are going to use a method called CreatePanel within a class called PanelMaker:

    type TPanelMaker = class (TObject) public function CreatePanel( aOwner : TWinControl; PanelBuilder : TBuilder ): TPanel; end;

    implementation

    function TPanelMaker.CreatePanel(aOwner : TWinControl; PanelBuilder : TBuilder ): TPanel; // Notice that thereare no // local variables such as // TempPanel and TempButton // These are kept local to the builder object begin PanelBuilder.BuildPanel( aOwner, 100, 200 );

    Page 1 sur 4Builder Design Pattern

    04/12/2007http://www.castle-cadenza.demon.co.uk/builder.htm

  • PanelBuilder.BuildEdit( 10, 10, 21, 100 ); PanelBuilder.BuildEdit( 40, 10, 21, 100 ); PanelBuilder.BuildEdit( 70, 10, 21, 100 ); CreatePanel := PanelBuilder.Panel; end;

    Notice that all we are doing is telling the builder what to do with the panel, rather than asking it for various components.

    The builder class looks like this:

    type TPanelBuilder = class (TObject) protected FButtonList : TList; FEditList : TList; FPanel: TPanel; function GetPanel: TPanel; virtual; public procedure BuildButton(Caption : string; Top : Integer; Left : Integer; Height : Integer; Width: Integer); virtual; procedure BuildEdit(Top : Integer; Left : Integer; Height : Integer; Width : Integer); virtual; procedure BuildPanel(aOwner : TWinControl; Height : Integer; Width : Integer); virtual; property Panel: TPanel read GetPanel; end;

    implementation

    procedure TPanelBuilder.BuildButton(Caption : string; Top : Integer; Left : Integer; Height : Integer; Width: Integer); var TempButton: TButton; begin TempButton := TButton.Create( FPanel );

    Page 2 sur 4Builder Design Pattern

    04/12/2007http://www.castle-cadenza.demon.co.uk/builder.htm

  • TempButton.Parent := FPanel; TempButton.Caption := Caption; TempButton.Top := Top; TempButton.Left := Left; TempButton.Height := Height; TempButton.Width := Width; end;

    procedure TPanelBuilder.BuildEdit(Top : Integer; Left : Integer; Height : Integer; Width : Integer); var TempEdit: TEdit; begin TempEdit := TEdit.Create( FPanel ); TempEdit.Parent := FPanel; TempEdit.Top := Top; TempEdit.Left := Left; TempEdit.Height := Height; TempEdit.Width := Width; end;

    procedure TPanelBuilder.BuildPanel(aOwner : TWinControl; Height : Integer; Width : Integer); begin FPanel := TPanel.Create( aOwner ); FPanel.Parent := aOwner; FPanel.Height := Height; Fpanel.Width := Width; end;

    function TPanelBuilder.GetPanel: TPanel; begin GetPanel := FPanel; end;

    Say that we want to change this, such that we want to make the default panel one with OK and Cancel buttons. All we have to do is sub class TPanelBuilder and override BuildPanel, thus:

    type TButtonPanelBuilder = class (TPanelBuilder) public

    Page 3 sur 4Builder Design Pattern

    04/12/2007http://www.castle-cadenza.demon.co.uk/builder.htm

  • procedure BuildPanel(aOwner : TWinControl; Height : Integer; Width : Integer); override; end;

    procedure TButtonPanelBuilder.BuildPanel(aOwner : TWinControl; Height : Integer; Width : Integer); var OKButton: TButton; CancelButton: TButton; begin inherited BuildPanel(aOwner, Height, Width); FPanel.Width := FPanel.Width + 60; // increase the size of the // panel to fit the buttons OKButton := TButton.Create( FPanel ); OKButton.Parent := FPanel; OKButton.Caption := 'OK'; OKButton.Top := FPanel.Top + 21; OKButton.Left := FPanel.Width - 60; OKButton.Width := 50; CancelButton := TButton.Create( FPanel ); CancelButton.Parent := FPanel; CancelButton.Caption := 'Cancel'; CancelButton.Top := OKButton.Top + OKButton.Top + 21; CancelButton.Left := FPanel.Width - 60; CancelButton.Width := 50; end;

    Page 4 sur 4Builder Design Pattern

    04/12/2007http://www.castle-cadenza.demon.co.uk/builder.htm