delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
497 Users Online NOW
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi



Loremo - the 1.5 liter car coming in 2009




Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (1)


Implementation of the State Design PatternFormat this article printer-friendly!Bookmark function is only available for registered users!
Product:
Delphi all versions
Category:
OO-related
Skill Level:
Scoring:
Last Update:
03/12/2002
Search Keys:
delphi delphi3000 article borland vcl code-snippet State Design Pattern Behavior Behavioral
Times Scored:
10
Visits:
3849
Uploader: Jochen Fromm
Company:
Reference: N/A
 
Question/Problem/Abstract:
How do you implement the State Design Pattern in Delphi ?
Answer:



Most programs provide toolbars with different tools. For
example Zoom-Buttons, Paint-Buttons (drawing of circles,
rectangles,.. ). When the Zoom-Button is pressed, the
user can zoom in or out, when the Paint-Button is pressed,
the user can paint s.th : each tool changes the behavior of
the program. You can realize this through different flags :

procedure TForm.FormMouseDown/FormMouseMove/FormMouseUp
begin
  ..
  if fZoomFlag then
  begin
    ...
  end else
  if fPaintFlag then
  begin
    ...
  end;
  ..
end;

Even if we want to create a simple program like MSPaint,
we will need a lot of flags :
fPenFlag, fDrawRectFlag, fDrawCircleFlag, fEraserFlag,...
This results in 'elephant'-procedures and a general view
becomes difficult.

You can avoid such 'elephant'-procedures through the state
design pattern. Gamma, Helm, Johnson and Vlissides
("Design Patterns", Addision-Wesley, 1995) define the
STATE design pattern in this way : it allows an object
to alter its behavior when its internal state changes.
The object will appear to change its class.

In our example, the behavior for each tool is encapsulated
in a different class :


  tTool = class
  private
    fForm : tForm;
  public
    constructor Create(Form : TForm);
    destructor Destroy; override;

    procedure SetCursor; virtual;
    procedure HandleMouseDown(x,y : integer); virtual;
    procedure HandleMouseMove(x,y : integer); virtual;
    procedure HandleMouseUp(x,y : integer); virtual;

    procedure StopAction; virtual;
  end;

  tZoomTool = class(tTool)
  public
    procedure SetCursor; override;
    procedure HandleMouseDown(x,y : integer); override;
    procedure HandleMouseMove(x,y : integer); override;
    procedure HandleMouseUp(x,y : integer); override;
  end;

  tPaintTool = class(tTool)
  public
    procedure SetCursor; override;
    procedure HandleMouseDown(x,y : integer); override;
    procedure HandleMouseMove(x,y : integer); override;
    procedure HandleMouseUp(x,y : integer); override;
  end;

Now we can replace all the flags by a simple parameter
fTool of class tTool. Instead of setting different flags,
an object of a derived class is created :

procedure TForm.SetZoomModus;
begin
  fTool.Destroy;
  fTool := tZoomTool.Create(Self);
end;

procedure TForm.SetPaintModus;
begin
  fTool.Destroy;
  fTool := tPaintTool.Create(Self);
end;


So that in the MouseDown/MouseMove/MouseUp events the
appropriate method is called :

procedure TForm.FormMouseDown(... X, Y: Integer);
begin
  fTool.HandleMouseDown(x,y);
end;

procedure TForm.FormMouseMove(... X, Y: Integer);
begin
  fTool.HandleMouseMove(x,y);
end;

procedure TForm.FormMouseUp(... X, Y: Integer);
begin
  fTool.HandleMouseUp(x,y);
end;






Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
What about the State of the Tool
    Jacco Kulman (Apr 12 2002 8:03AM)

By destroying and recreating the tool you might loose important state of the tool. In my honest opinion it would be better to have a two tool members Paint an Zoom created like this:

procedure TForm.FormCreate(Sender: TObject);
begin
  fZoomTool := tZoomTool.Create(Self);
  fPaintTool := tPaintTool.Create(Self);
end;

procedure TForm.SetZoomModus;
begin
  fActiveTool := fZoomTool;
end;

procedure TForm.SetPaintModus;
begin
  fActiveTool := fPaintTool;
end;


So that in the MouseDown/MouseMove/MouseUp events the
appropriate method is called :

procedure TForm.FormMouseDown(... X, Y: Integer);
begin
  fActiveTool.HandleMouseDown(x,y);
end;

procedure TForm.FormMouseMove(... X, Y: Integer);
begin
  fActiveTool.HandleMouseMove(x,y);
end;

procedure TForm.FormMouseUp(... X, Y: Integer);
begin
  fActiveTool.HandleMouseUp(x,y);
end;

Regards Jacco

P.S: I think calling destroy is not the standard way to go. Always call Free (this will prevent exceptions when freeing nil).

Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
E. Irigoyen
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)