ITPub博客

首页 > 应用开发 > IT综合 > 转载---Dephi状态模式(State模式)

转载---Dephi状态模式(State模式)

原创 IT综合 作者:uuxa 时间:2007-09-10 21:57:22 0 删除 编辑

对于面向对象开发来说,很长的函数和过程是不容易维护的,同样冗长的if else 以及case of的条件判断语句会使得代码不够清晰,特别是当条件判断很多时,比如有几十条甚至十几条条件判断语句,会使得代码难以修改和维护。

在早期windows开发中,程序员经常需要编写巨大的消息判断语句,根据消息的不同调用不同的消息处理函数,后来为了改善消息处理的复杂程度,Delphi引入了message关键字,从编译器一级对消息处理进行了映射,减少了条件判断语句的大量使用,这一案例就是巨大的条件判断语句弊端的典型体现。

通常说来,if else 以及case 语句都是对对象的某个状态或者属性进行判断,根据对象的状态或属性的不同,执行不同的操作。实际上就是一个有限状态机,为了消除这些if else条件判断语句,我们可以使用State模式来解决。

[@more@]

所谓状态模式就是将宿主对象中每一种可能的状态抽象成一个状态类,当宿主对象的状态发生变化时,宿主对象改变自己的状态,并执行不同状态类对应的不同操作。State模式的缺点,就是如果宿主对象的状态比较多的话,会产生大量的小粒度的对象,显得对象过多,体系不紧凑。

另外,State模式的模型图和策略模式的模型图几乎一样,区别在于状态模式的特点是状态会经常发生变化,而策略模式一般来说在使用的时候通常是固定的,不会频繁变化。另外两个模式的目的也不同,对状态改变时,对象具有不同的行为进行抽象,对应于State模式。而策略模式则是为了解决算法的互换问题的。

状态模式使用示例

在Delphi的demosdocgraphex目录下,提供了一个画图程序的例子,运行后可以根据当前绘图工具的不同,绘制不同的形状,其中核心的绘图部分就是一个大的添加判断过程DrawShape,根据当前绘图工具的不同(线、圆、矩形、圆角矩形),绘制不同的形状,代码如下:

procedure TForm1.DrawShape(TopLeft, BottomRight: TPoint; AMode: TPenMode);

begin
  with Image.Canvas do
  begin
    Pen.Mode := AMode;
    case DrawingTool of
      dtLine:
        begin
          Image.Canvas.MoveTo(TopLeft.X, TopLeft.Y);
          Image.Canvas.LineTo(BottomRight.X, BottomRight.Y);
        end;
      dtRectangle: Image.Canvas.Rectangle(TopLeft.X, TopLeft.Y, BottomRight.X,
        BottomRight.Y);
      dtEllipse: Image.Canvas.Ellipse(Topleft.X, TopLeft.Y, BottomRight.X,
        BottomRight.Y);
      dtRoundRect: Image.Canvas.RoundRect(TopLeft.X, TopLeft.Y, BottomRight.X,
        BottomRight.Y, (TopLeft.X - BottomRight.X) div 2,
        (TopLeft.Y - BottomRight.Y) div 2);
    end;
  end;
end;
下面我们就对这一例子使用State模式进行改造,消除Case判断

修改后的代码如下:

type
 
  TDrawingTool = class(TObject)
  private
    FImage: TImage;
  public
    constructor Create(AImage: TImage);
    procedure DrawShape(TopLeft, BottomRight: TPoint; AMode: TPenMode); virtual;
      abstract;
  end;
 
  TLineTool = class(TDrawingTool)
    procedure DrawShape(TopLeft, BottomRight: TPoint; AMode: TPenMode);
      override;
  end;
 
  TRectTool = class(TDrawingTool)
    procedure DrawShape(TopLeft, BottomRight: TPoint; AMode: TPenMode);
      override;
  end;
 
  TRoundRectTool = class(TDrawingTool)
    procedure DrawShape(TopLeft, BottomRight: TPoint; AMode: TPenMode);
      override;
  end;
 
  TEllipseTool = class(TDrawingTool)
    procedure DrawShape(TopLeft, BottomRight: TPoint; AMode: TPenMode);
      override;
  end;
 
  TForm1 = class(TForm)
  private
    FDrawingTool: TDrawingTool;
    procedure SetDrawingTool(const Value: TDrawingTool);
    { Private declarations }
  public
    { Public declarations }
    procedure DrawShape(TopLeft, BottomRight: TPoint; AMode: TPenMode);
    property DrawingTool: TDrawingTool read FDrawingTool write SetDrawingTool;
  end;
 
 
procedure TForm1.LineButtonClick(Sender: TObject);
begin
  FreeAndNil(FDrawingTool);
  DrawingTool := TLineTool.Create(Image);
end;
 
procedure TForm1.RectangleButtonClick(Sender: TObject);
begin
  FreeAndNil(FDrawingTool);
  DrawingTool := TRectTool.Create(Image);
end;
 
procedure TForm1.EllipseButtonClick(Sender: TObject);
begin
  FreeAndNil(FDrawingTool);
  DrawingTool := TEllipseTool.Create(Image);
end;
 
procedure TForm1.RoundRectButtonClick(Sender: TObject);
begin
  FreeAndNil(FDrawingTool);
  DrawingTool := TRoundRectTool.Create(Image);
end;
 
procedure TForm1.DrawShape(TopLeft, BottomRight: TPoint; AMode: TPenMode);
begin
  DrawingTool.DrawShape(TopLeft, BottomRight, AMode);
end;
 
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  LineButton.OnClick(nil);
end;
 
 
{ TEllipseTool }
 
procedure TEllipseTool.DrawShape(TopLeft, BottomRight: TPoint;
  AMode: TPenMode);
begin
  with FImage.Canvas do
  begin
    Pen.Mode := AMode;
    Ellipse(Topleft.X, TopLeft.Y, BottomRight.X,
      BottomRight.Y);
  end;
end;
 
{ TRoundRectTool }
 
procedure TRoundRectTool.DrawShape(TopLeft, BottomRight: TPoint;
  AMode: TPenMode);
begin
  with FImage.Canvas do
  begin
    Pen.Mode := AMode;
    RoundRect(TopLeft.X, TopLeft.Y, BottomRight.X,
      BottomRight.Y, (TopLeft.X - BottomRight.X) div 2,
      (TopLeft.Y - BottomRight.Y) div 2);
  end;
end;
 
{ TRectTool }
 
procedure TRectTool.DrawShape(TopLeft, BottomRight: TPoint;
  AMode: TPenMode);
begin
  with FImage.Canvas do
  begin
    Pen.Mode := AMode;
    Rectangle(TopLeft.X, TopLeft.Y, BottomRight.X, BottomRight.Y);
  end;
end;
 
{ TLineTool }
 
procedure TLineTool.DrawShape(TopLeft, BottomRight: TPoint;
  AMode: TPenMode);
begin
  with FImage.Canvas do
  begin
    Pen.Mode := AMode;
    MoveTo(TopLeft.X, TopLeft.Y);
    LineTo(BottomRight.X, BottomRight.Y);
  end;
end;
 
procedure TForm1.SetDrawingTool(const Value: TDrawingTool);
begin
  FDrawingTool := Value;
end;
 
{ TDrawingTool }
 
constructor TDrawingTool.Create(AImage: TImage);
begin
  FImage := AImage;
end;
 
end.

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/7416120/viewspace-968816/,如需转载,请注明出处,否则将追究法律责任。

上一篇: 数据库设计
下一篇: 半月痕
请登录后发表评论 登录
全部评论
  • 博文量
    111
  • 访问量
    281327