設計模式、用Delphi實現---->Singleton 模式 (轉)

worldblog發表於2007-12-09
設計模式、用Delphi實現----&gtSingleton 模式 (轉)[@more@]

起源

的SINGLETON模式是在SINGLETON的基礎上進行了擴充套件。更多SINGLETON模式的資料請參閱 《設計模式84頁》:namespace prefix = o ns = "urn:schemas--com::office" />

目的

保證一個類僅有一個例項,並提供一個訪問它的全域性訪問點,一個相對簡單的應用型設計模式

動機

此模式最重要的是保證大量類正確的訪問單個例項。儘管一臺個可能有多臺印表機,但系統只允許有且只有一個列印快取。同樣比如:一個系統只有一個系統、一個窗體管理系統。對於Delphi的VCL來說:大家天天接觸的Tapplication,Tscreen,Tclipboard都是。此模式更好的是使你可以在任何時候為你的應用提供一個全域性。其它的用途:可以、提供一些全域性的異常控制程式碼,控制,為跨程式提供單一的訪問點。

怎樣保持一個類只有一個例項並且建立好的訪問?一個全域性變數保證了例項的可訪問性,但還沒有保證多個例項的同時存大的可能。

一個好的解決方案:建立類自身來負責保持自身一個例項的機制。類的第一個例項能儲存不會再有類的例項被建立(在建立類的新例項時請求被中段)。並提供一個訪問類的方法。這就是我們的singleton模式,典型的應用是建立服務型的的類。

 

應用

假設有一個用於顯示時間進度低階服務類Tprogressor。類包括兩個典型的方法:StartProgress, EndProgress, Abort 和一些常用的屬性如:Progress, Aborted其它。

下面程式碼是Tprogressor類的介面部份

type

  TProgressor = class (T)

  private

  FProgress: Integer;

  protected

  procedure SetProgress(Value: Integer);

  public

»  procedure StartProgress;

»  property Progress: Integer read FProgress write SetProgress;

  end;

 

下面的程式碼是應用了singleton模式後的類的的介面部份。

type

  TProgressor = class (TObject)

  private

  FProgress: Integer;

  protected

  constructor CreateInstance;

  class function AccessInstance(Request: Integer): TProgressor;

  procedure SetProgress(Value: Integer);

  public

  constructor Create;

  destructor Destroy; overr;

  class function Instance: TProgressor;

  class procedure ReleaseInstance;

»  procedure StartProgress;

»  property Progress: Integer read FProgress write SetProgress;

  end;

 

類介面部份的介紹:

·  方法class function Instance用於訪問類的單件的例項。此方法一般在第一時間訪問,類的例項被建立。

·  類構造器被過載,如果你嘗試著不透過instance方法來構建一個新的例項將會丟擲一個異常。

·  可透過ReleaseInstance來清除單件類存在的例項。一般在你要清除部件時調節器用些方法。在Delphi 1 exit過程中呼叫,在Delphi 2/3/4/5/6中在單元finalization中呼叫。不要訪問TProgressor.Instance.Free來清除例項,

 

現在讓我們來看看singleton模式實現。

constructor TProgressor.Create;

begin

  inherited Create;

  raise Exception.CreateFmt('Access class %s through Instance only',

  [ClassName]);

end;

 

constructor TProgressor.CreateInstance;

begin

  inherited Create;

end;

 

destructor TProgressor.Destroy;

begin

  if AccessInstance(0) = Self then AccessInstance(2);

  inherited Destroy;

end;

 

class function TProgressor.AccessInstance(Request: Integer): TProgressor;

  const FInstance: TProgressor = nil;

begin

  case Request of

  0 : ;

  1 : if not Assigned(FInstance) then FInstance := CreateInstance;

  2 : FInstance := nil;

  else

  raise Exception.CreateFmt('Illegal request %d in AccessInstance',

  [Request]);

  end;

  Result := FInstance;

end;

 

class function TProgressor.Instance: TProgressor;

begin

  Result := AccessInstance(1);

end;

 

class procedure TProgressor.ReleaseInstance;

begin

  AccessInstance(0).Free;

end;

 

procedure TProgressor.SetProgress(Value: Integer);

begin

»加入實現程式碼

end;

 

procedure TProgressor.StartProgress;

begin

»加入實現程式碼

end;

 

此模式的密秘在AccessInstance方法,AccessInstance方法使用了常量來存放例項。

由於Delphi不支援靜態類欄位的原因,你必需使用此方法。AccessInstance根據請求的引數來確認不同的返回方式,返回當前例項(Request = 0),建立一個例項(Request = 1),重置例項(Request = 2)。Delphi 2/3/4/5/6中,你必須將設定$J+來支援形式常量(參見Delphi線上幫助)

將CreateInstance設成保護方法(protected),我們確保了其它類不能呼叫類的構造器。但由於構造本身為虛擬函式的原因,它可以被後代過載。例中,當第一次呼叫類例項時將確認類的具體型別。

唯一需要你手動新增的程式碼是:在單元的initialization或finalization加入清除程式碼。

下面是應用例項(Delphi1.0)

 

unit ProgressorTest;

 

...

...

 

implementation

 

...

...

 

procedure ShutDown; far;

begin

» TProgressor.ReleaseInstance;

end;

 

initialization

MMWIN:START INITIALIZATION

» AddExitProc(ShutDown);

end.

 

具體操作Tprogressor的程式碼:

 

procedure TSomeClass.DoSomething;

var I: Integer;

begin

» TProgressor.Instance.StartProgress;

» for I := 0 to 100 do

» begin

»  TProgressor.Instance.Progress := I;

» ..{ 完成其它的工作}

» end;

» TProgressor.Instance.EndProgress;

end;

Delphi例項

正在組織


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990472/,如需轉載,請註明出處,否則將追究法律責任。

相關文章