麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > Delphi > 正文

兩種Delphi實現Singleton模式方法

2019-11-18 18:39:16
字體:
來源:轉載
供稿:網友
 

兩種Delphi實現Singleton模式方法

haozi


摘  要 本文描述了兩種Singleton模式的Delphi實現方式,并做了對比分析。
關鍵字 設計模式,Singleton

Singleton(單件)模式是一種很有用的設計模式。它的意圖的是:僅僅創建一個類的實例,并提供一個訪問它的全局訪問點。全局變量使的一個對象易被訪問,但不能防止你實例化多個對象。單件模式的目的就是確保在程序的生命周期內只有一個實例存在。
看下面的代碼:
PRocedure TForm1. Button1Click(Sender: TObject);
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模式的幾種方法。

一.基于override兩個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實現在網上還能查著其他的一些實現方式,本文的兩種方法上

最常見的和簡單的。同時其它方法的思路也很跟以上兩方法很相似。


上一篇:SGIP的delphi原碼

下一篇:Delphi中關于TApplication類的詳解

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

主站蜘蛛池模板: 欧美一级全黄 | 精品久久一区二区 | 202z中文字幕第一页 | 国产黄色毛片 | 国产精品美女一区二区 | 国产精品自拍99 | 国产精品av久久久久久无 | 牛牛a级毛片在线播放 | 免费国产自久久久久三四区久久 | 特黄一级小说 | 又黄又爽免费无遮挡在线观看 | 精品国产91久久久久久久妲己 | 黄色免费小视频网站 | 杏美月av| 色淫网站免费视频 | 在线成人免费网站 | 国产一区精品在线观看 | 竹内纱里奈和大战黑人 | 国产1区2| 草妞视频| 激情视频导航 | lutube成人福利在线观看污 | 国产精品免费大片 | 成人在线观看地址 | av在线大全 | 亚洲第一精品在线 | 国产资源在线观看视频 | 免费国产自久久久久三四区久久 | 香蕉成人在线观看 | av日韩一区二区三区 | 毛片在线免费视频 | 久久国产夫妻视频 | 九九热视频这里只有精品 | 欧美成人高清视频 | 欧美成人精品一区二区三区 | 久久久国产精品成人免费 | 色婷婷久久久亚洲一区二区三区 | 久久亚洲美女视频 | 亚洲一区二区三区日本久久九 | 制服丝袜日日夜夜 | 九九热这里只有精品8 |