兩種Delphi實現Singleton模式方法 (轉)
兩種實現Singleton方法
haozi
摘 要 本文描述了兩種Singleton模式的Delphi實現方式,並做了對比分析。
關鍵字 設計模式,Singleton
Singleton(單件)模式是一種很有用的設計模式。它的意圖的是:僅僅建立一個類的例項,並提供一個訪問它的全域性訪問點。全域性變數使的一個易被訪問,但不能防止你例項化多個物件。單件模式的目的就是確保在的生命週期內只有一個例項存在。
看下面的程式碼:
procedure TForm1. Button1Click(Sender: T);
var lS1 : TSingleton; l
S2 : TSingleton;
begin
try lS1 := TSingleton.Create; ////類的構造器
lS2 := TSingleton.Create; ////呼叫類的構造器
//// ...別的程式碼
finally
lS1.Free; ////釋放物件
lS2.Free; ////釋放物件
end;
end;
在上面的程式碼中第一次呼叫Create時TSingleton類被例項化,lS1指向一個存放物件的地址,當第二次呼叫TSingleton.Create函式時又重新例項化了TSingleton物件,lS2指向記憶體分配的另一個地址。Singleton模式就是讓類自己負責儲存他的唯一例項。
在上面的程式碼中就是讓lS2建立的時候也指向lS1指向的物件(也就是被分配同一個記憶體地址),同樣我們在釋放lS1時必須防止記憶體被釋放,因為單件物件還被lS2所引用。從而保證在程式的生命週期內有且只有一個類例項。
《設計模式》C++的示例程式碼是使用C++的靜態成員變數儲存例項的,同時使用protected的構造器函式。但是在Delphi中由於沒有靜態成員變數,所以不能原樣的使用該單件模式示例的方法。以下我們分析兩種DELPHI實現Singleton模式的幾種方法。
一.基於overr兩個Tobject虛擬函式的方法
class function NewInstance: TObject; virtual;
procedure FreeInstance; virtual;
NewInstance函式負責類物件建立的時候為物件分配記憶體,FreeInstance則相反釋放記憶體
。
前者在物件構造時呼叫,後者在物件析構時呼叫。
我們使用兩個全域性變數來儲存單件物件和物件的引用記數。
var Instance : TSingleton = nil;
RefCount : Integer = 0;
TSingleton類的單元:
////---------------------------------------------------------------------------
////
unit uSingleton;
interface
type
TSingleton = class(TObject)
public
class function NewInstance: TObject; override; ////覆蓋基類函式
procedure FreeInstance; override; ////覆蓋基類函式
class function RefCount: Integer; ////返回當前引用記數
end;
//// Declaration global variables
var
Instance: TSingleton = nil;
RefCount: Integer = 0;
implementation
{ TSingleton }
procedure TSingleton.FreeInstance;
begin
Dec( RefCount ); ////減少引用記數
if ( RefCount = 0 ) then ////是否為0,是則釋放記憶體
begin
Instance := nil;
//// 釋放單件類的私有變數
////…
inherited FreeInstance;
end;
end;
class function TSingleton.NewInstance: TObject;
begin
if ( not Assigned( Instance ) ) then
begin
Instance := TSingleton(inherited NewInstance);
////初始化私有變數 例子:
//// Instance.VariableName := Value;
end;
Result := Instance ;
Inc( RefCount );
end;
class function TSingleton.RefCount: Integer;
begin
Result := RefCount;
end;
end.
////---------------------------------------------------------------------------
////
當呼叫TSingleton的構造器的時候,會呼叫我們override的NewInstance函式,由NewInstance分配記憶體並返回給構造器,這樣透過override的NewInstance函式我們確保了Create函式只可能例項化一個TSingleton物件(無論呼叫多少次Create只返回第一次分配的記憶體地址)。同時RefCount變數儲存我們有幾個到物件的引用。
我們在來看測試程式碼
procedure TForm1.Button1Click(Sender: TObject);
var
lS1, lS2: TSingleton;
Ob1, Ob2: Tobject;
begin
lS1 := TSingleton.Create;
ShowMessage(IntToStr(RefCount)); //// Ref_Count = 1
lS2 := TSingleton.Create;
ShowMessage(IntToStr(RefCount)); //// Ref_Count = 2
Ob1 := TObject.Create;
Ob2 := Tobject.Create;
if lS1 = lS2 then
ShowMessage('地址相等') //// lS1 = lS2
else
ShowMessage('地址不相等');
if Ob1 = Ob2 then
ShowMessage('地址相等')
else
ShowMessage('地址不相等'); //// Ob1 <> Ob2
end;
當程式呼叫析構器的時候(就是呼叫FREE函式的時候),析構器會呼叫FreeInstance函式釋放被構造器分配的記憶體。Override的FreeInstance函式保證引用記數為零的時候才釋放單件模式物件的記憶體。
下面是我們的測試程式碼:
var
lS1 : TSingleton;
lS2 : TSingleton;
begin
try
lS1 := TSingleton.Create; ////呼叫類的構造器
lS2 := TSingleton.Create; ////呼叫類的構造器
//// ...別的程式碼
finally
lS1.Free; ////這裡會首先呼叫我們覆蓋定義的FreeInstance,
////由於這時RefCount在減1後為1,單件物件沒有被釋放
lS2.Free; ////dec(RefCount)= 0 釋放單件物件
end;
end;
上面這種單件模式實現方法很好地實現了由類自身來負責儲存自己的唯一例項(透過擷取建立新物件的請求——參考《設計模式》。它對TSingleton類的使用沒有特殊的限制——程式設計師可以隨意的呼叫Create和Free函式。
本模式的缺點是:該TSingleton類不能作為父類繼承生成子類。如果繼承生成兩個子類,Create時只產生一個物件。
procedure TForm1.Button1Click(Sender: TObject);
var
lS1 : 子類一;
lS2: 子類二;
begin
lS1 := 子類一.Create;
lS2 := 子類二.Create; ////不會建立子類二,lS2將指向lS1指向的記憶體,
////也就是 lS1 = lS2end;
二.《設計模式》上示例的Delphi實現
《設計模式》的實現示例是透過私有構造器函式來實現控制只產生一個物件例項。但該給出的C++程式碼實現未給出物件如何釋放。Delphi裡面不能實現Create函式的私有化,我們新定義一個函式來代替Create函式,同時遮蔽父類的Create函式。程式碼如下
:
////---------------------------------------------------------------------------
////
unit uSingletonUnit;
interface
uses
Classes, SysUtils;
type
TCSingleton = class(TComponent) ////從Tcomponent類繼承來。
private
constructor CreateInstance(AOwner: TComponent); ////傳遞Owner引數
//// 這樣TCSingleton類物件就會隨Owner一起銷燬(擁有者負責銷燬TCSingleton物件)
public
constructor Create(AOwner: TComponent); override;
class function Instance(AOwner: TComponent): TCSingleton;
end;
var
gCSingleton: TCSingleton; //// Global variables
implementation
{ TCSingleton }
constructor TCSingleton.Create(AOwner: TComponent);
begin
////遮蔽Create函式的功能
raise Exception.CreateFmt('Access class %s through Instance only',
[ClassName]);
end;
constructor TCSingleton.CreateInstance(AOwner: TComponent);
begin
////新定義的建構函式Private型的
inherited Create(AOwner);
end;
class function TCSingleton.Instance(AOwner: TComponent): TCSingleton;
begin
if not Assigned(gCSingleton) then
gCSingleton := TCSingleton.CreateInstance(AOwner);
Result := gCSingleton;
end;
end.
////--------------------------------------------------------------------------/
/
上面的實現類使用過程中,程式設計師不用考慮單件模式物件的銷燬問題。只是不能呼叫Create,必須呼叫Instance函式來獲得物件的例項,同時把單件擁有者作為引數傳遞到函式里。這種實現方法可以作為基類被繼承,用在狀態模式的單件裡(參見參考文獻4),實現時的多型。
三.結束語
Singleton 模式的Delphi實現在網上還能查著其他的一些實現方式,本文的兩種方法上
最常見的和簡單的。同時其它方法的思路也很跟以上兩方法很相似。
以上例子均沒有考慮多執行緒的情況。
作者E:">wuch@km169.net
參考文獻:
1.《Creating a real singleton class in Delphi》 by Lasse
2.《Delphi 5 開發人員指南》機械工業出版社 2000.7
3.《設計模式》機械工業出版社 2000.9
4.《UML和模式應用》機械工業出版社 2002.1等
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-995947/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Singleton模式之Delphi實現 (轉)模式
- 設計模式、用Delphi實現---->Singleton 模式 (轉)設計模式
- 實現AS3的Singleton的兩種方法S3
- singleton模式的實現方法有很多種麼?模式
- C++完美實現Singleton模式[轉]C++模式
- 設計模式、用Delphi實現---->Builder模式 (轉)設計模式UI
- [DELPHI]單例模式(singleton) 陳省單例模式
- JScript下Singleton模式的實現。 (轉)JS模式
- 請教兩種Singleton Pattern 實現方式的區別!
- Python單例模式(Singleton)的N種實現Python單例模式
- singleton模式四種執行緒安全的實現模式執行緒
- JAVA中實現單例(Singleton)模式的八種方式Java單例模式
- C++用多種方式實現Singleton單例模式C++單例模式
- 三種Singleton的實現方式
- 單利模式的兩種最佳實現模式
- 關於多型實現Singleton模式的探討 (轉)多型模式
- Java Singleton的3種實現方式Java
- C++設計模式:Singleton的模板實現之一 (轉)C++設計模式
- Singleton——單例模式(8種)單例模式
- 兩種方法使vue實現jQuery呼叫VuejQuery
- C#實現Web檔案上傳的兩種方法(轉)C#Web
- 在網頁中實現細線邊框的兩種方法(轉)網頁
- Golang兩種方法實現MD5加密Golang加密
- 兩個數換值四種方法實現
- Java中Singleton的三種實現方式解析Java
- singleton模式的一種變體:double-checked locking (轉)模式
- 單例模式——執行緒安全的兩種實現單例模式執行緒
- RabbitMQ實現延時訊息的兩種方法MQ
- html兩種方法來實現tab切換效果HTML
- 表格細邊框的兩種CSS實現方法CSS
- vue 跳轉的兩種方法Vue
- Python 5種方法實現單例模式Python單例模式
- Java 實現單例模式的 9 種方法Java單例模式
- Delphi系列談之:Delphi中的靜態屬性及靜態方法的實現 (轉)
- 實現單例模式的 9 種方法,你知道幾種?單例模式
- Python實現"數字轉換為十六進位制"的兩種方法
- python用兩種方法實現url短連線Python
- Drawable轉換為Bitmap兩種方法