中国程序员联盟 正在重新改版中ing 不便之处还请见谅 改版后将内容涉及java delphi .net php
 
  首页 | 数据库开发 | 网络通讯 | 多线程 | 多媒体开发 | 图像处理 | 程序人生 | 系统函数 | 控件开发 | Web服务
 
  当前位置:笨鱼delphi技术网>数据库开发>设计模式>文章内容

delphi Template Pattern (模板)

来源:站内 关于:bill 发布时间:2007-06-23   [收藏] [推荐]

Defines the skeleton of an algorithm in an operation, deferring some steps to subclasses without changing the algorithm's structure.

Good for

  • encapsulating a policy that is deployed by many different agents
  • reusing the code in a complex algorithm by encapsulating invariable parts and letting subclasses implement the behavior that can vary
  • providing hook operations at specific points that a subclass can extend, but requiring to be callable through the template method on the base class.

Structure of the Template Pattern

Template Graphic

Implementation of the Template Pattern

The Template pattern has several examples in the DelphiVCL, as might be expected in any object framework. In this sample, the VCL's TStream abstract class (classes.pas) implements stream copying in the template method CopyFrom(), which abstracts the algorithm for reading data from a stream and preparing its destination. TStream defers the implementation of Read() and Write() methods to its subclasses by declaring them as abstract methods. CopyFrom() uses Read() and Write() via the ReadBuffer() and WriteBuffer() methods, which are themselves template methods-since they are static and simply provide an interface to Read() and Write() virtual methods. Read() and Write() are the specific extension points that must be implemented in derived classes.

For implementation details, please review the VCL's classes.pas unit, the TStream abstract class, and the concrete stream classes: TCustomMemoryStream/TMemoryStream and TStringStream; or download Streams.hlp.

Since you want users of your class to override the specific extension points and not the interface provided by the template method, a template method is usually declared statically on the base class, and the primitive methods are virtual.

 
{ TStream abstract class }
TStream = class(TObject)
  private
  ...
  protected
    procedure SetSize(NewSize: Longint); virtual;
  public
  
    // primitive operations to be provided by derived classes
    function Read(var Buffer; Count: Longint): Longint; virtual; abstract;
    function Write(const Buffer; Count: Longint): Longint; virtual; abstract;
    function Seek(Offset: Longint; Origin: Word): Longint; virtual; abstract;
    
        // template methods

     procedure ReadBuffer(var Buffer; Count: Longint);
    procedure WriteBuffer(const Buffer; Count: Longint);
    
    // acts as template method by encapsulating the copy algorithm
    function CopyFrom(Source: TStream; Count: Longint): Longint;
    ...
end;

// concrete class
TStringStream = class(TStream)
  ...
  public
    constructor Create(const AString: string);
    // concrete class implementations - varying behavior
    function Read(var Buffer; Count: Longint): Longint; override;
    ...
    function Write(const Buffer; Count: Longint): Longint; override;
    ...
end;

{ TStream }  // abstract class
  ...
// template methods

procedure TStream.ReadBuffer(var Buffer; Count: Longint);
begin
if
(Count <> 0) and (Read(Buffer, Count) <> Count) then raise EReadError.Create(SReadError); end; procedure TStream.WriteBuffer(const Buffer; Count: Longint);
begin if (Count <> 0) and (Write(Buffer, Count) <> Count) then raise EWriteError.Create(SWriteError); end;
function TStream.CopyFrom(Source: TStream; Count: Longint): Longint; const
MaxBufSize = $F000; var BufSize, N: Integer; Buffer: PChar;
begin if Count = 0 then begin Source.Position := 0; Count := Source.Size; end; Result := Count; if Count > MaxBufSize then BufSize := MaxBufSize else BufSize := Count; GetMem(Buffer, BufSize); try while Count <> 0 do begin if Count > BufSize then N := BufSize else N := Count; Source.ReadBuffer(Buffer^, N); WriteBuffer(Buffer^, N); Dec(Count, N); end; finally FreeMem(Buffer, BufSize); end; end; { TStringStream } // concrete class ...; // concrete class implementation of primitive operations function TStringStream.Read(var Buffer; Count: Longint): Longint; begin Result := Length(FDataString) - FPosition; if Result > Count then Result := Count; Move(PChar(@FDataString[FPosition + 1])^, Buffer, Result); Inc(FPosition, Result); end; function TStringStream.Write(const Buffer; Count: Longint): Longint; begin Result := Count; SetLength(FDataString, (FPosition + Result)); Move(Buffer, PChar(@FDataString[FPosition + 1])^, Result); Inc(FPosition, Result); end; ...

[浏览: 次]   
上一篇:delphi Singleton Pattern (设计模式)   下一篇:delphi Strategy Pattern (策略)
[收藏] [推荐] [返回顶部] [打印本页] [关闭窗口]  
    评论加载中…
google adsense热点文章
·delphi COM+对象缓冲池
·delphi Delphi_Delphi面向对象编程的20
·delphi Singleton Pattern (设计模式)
·delphi Observer Pattern
·delphi Adapter Pattern
·delphi Strategy Pattern (策略)
     delphi技术网 | firefox 下载 | Avant Browser下载 | dedecms 技术网 | drupal 爱好者 | php 技术网
  Copyright@www.delphichm.com,2006-2009.All Rights Reserved.
 
程序员联盟 | delphi Java .net|QQ:707102932