轉載---Dephi狀態模式(State模式)
對於物件導向開發來說,很長的函式和過程是不容易維護的,同樣冗長的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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 狀態模式(State)模式
- 狀態模式(State pattern)模式
- 設計模式之狀態模式(State)設計模式
- 設計模式-狀態模式(State Pattern)設計模式
- 設計模式——20狀態模式(State)設計模式
- 設計模式之狀態模式---State Pattern設計模式
- C#設計模式系列:狀態模式(State)C#設計模式
- 設計模式--狀態模式State(行為型)設計模式
- JAVA設計模式之 狀態模式【State Pattern】Java設計模式
- .NET下的狀態(State)模式 ------行為型模式模式
- 設計模式之策略模式和狀態模式(strategy pattern & state pattern)設計模式
- 【設計模式基礎】行為模式 - 8 -狀態(State)設計模式
- 23種設計模式 之 State模式(狀態模式)[C語言實現]設計模式C語言
- 狀態模式模式
- 設計模式-狀態模式設計模式
- 設計模式:狀態模式設計模式
- 使用C# (.NET Core) 實現狀態設計模式 (State Pattern)C#設計模式
- 行為型模式:狀態模式模式
- 設計模式(十五)狀態模式設計模式
- 設計模式之——狀態模式設計模式
- javascript設計模式狀態模式JavaScript設計模式
- 設計模式(六):狀態模式設計模式
- JavaStatePattern(狀態模式)JavaAST模式
- JS 狀態模式JS模式
- (三)狀態模式模式
- PHP 設計模式之狀態模式PHP設計模式
- 簡說設計模式——狀態模式設計模式
- python設計模式狀態模式Python設計模式
- 設計模式20之狀態模式設計模式
- 極簡設計模式-狀態模式設計模式
- GoLang設計模式14 - 狀態模式Golang設計模式
- Python設計模式-狀態模式Python設計模式
- Java設計模式之狀態模式Java設計模式
- 設計模式系列之「狀態模式」設計模式
- 詳解 state 狀態模式及在 C++ 設計模式程式設計中的使用例項C++設計模式程式設計
- 狀態變化模式模式
- 17_狀態模式模式
- 設計模式--直譯器模式和狀態模式設計模式