まず"シングルトンもどき"です。
unit Unit4; interface type TSingleton = class(TObject) private FTestValue: Integer; public class constructor Create; class destructor Destroy; constructor Create; destructor Destroy; override; property TestValue: Integer read FTestValue write FTestValue; end; function Singleton: TSingleton; implementation var FSingleton: TSingleton; function Singleton: TSingleton; begin if FSingleton = nil then begin FSingleton := TSingleton.Create; end; Result := FSingleton; end; class constructor TSingleton.Create; begin FSingleton := nil; end; class destructor TSingleton.Destroy; begin FSingleton.Free; end; constructor TSingleton.Create; begin inherited; { Initialize } FTestValue := 0; end; destructor TSingleton.Destroy; begin { Finalize } inherited; end; end.
次に"本当の"シングルトンです。
unit Unit8; interface uses SysUtils; type TSingleton = class(TObject) private FTestValue: Integer; class var FSingleton: TSingleton; constructor CreateInstance; public class constructor Create; class destructor Destroy; constructor Create; destructor Destroy; override; class function GetInstance: TSingleton; property TestValue: Integer read FTestValue write FTestValue; end; ECreateSingleton = class(Exception) end; implementation { TSingleton } class constructor TSingleton.Create; begin FSingleton := nil; end; class destructor TSingleton.Destroy; begin FSingleton.Free; end; constructor TSingleton.Create; begin raise ECreateSingleton.Create('TSingleton.Create cannot use.'); end; constructor TSingleton.CreateInstance; begin inherited Create; { Initialize } FTestValue := 0; end; destructor TSingleton.Destroy; begin { Finalize } inherited; end; class function TSingleton.GetInstance: TSingleton; begin if FSingleton = nil then begin FSingleton := TSingleton.CreateInstance; end; Result := FSingleton; end; end.
CriticalSectionによる排他処理を加えたものです。
unit Unit12; interface uses SysUtils, Windows; type TSingleton = class(TObject) private FTestValue: Integer; class var FSingleton: TSingleton; FCriticalSection: TRTLCriticalSection; constructor CreateInstance; public class constructor Create; class destructor Destroy; constructor Create; destructor Destroy; override; class function GetInstance: TSingleton; property TestValue: Integer read FTestValue write FTestValue; end; ECreateSingleton = class(Exception) end; implementation { TSingleton } type TInitializeCriticalSectionExFunc = function(var lpCriticalSection: TRTLCriticalSection; dwSpinCount: DWORD; Flags: DWORD): BOOL; stdcall; const CRITICAL_SECTION_NO_DEBUG_INFO = $01000000; class constructor TSingleton.Create; var InitializeCriticalSectionEx: TInitializeCriticalSectionExFunc; begin FSingleton := nil; @InitializeCriticalSectionEx := GetProcAddress(GetModuleHandle(kernel32), 'InitializeCriticalSectionEx'); if Assigned(InitializeCriticalSectionEx) = True then begin InitializeCriticalSectionEx(FCriticalSection,0,CRITICAL_SECTION_NO_DEBUG_INFO); end else begin InitializeCriticalSectionAndSpinCount(FCriticalSection,0); end; end; class destructor TSingleton.Destroy; begin DeleteCriticalSection(FCriticalSection); FSingleton.Free; end; constructor TSingleton.Create; begin raise ECreateSingleton.Create('TSingleton.Create cannot use.'); end; constructor TSingleton.CreateInstance; begin inherited Create; { Initialize } FTestValue := 0; end; destructor TSingleton.Destroy; begin { Finalize } inherited; end; class function TSingleton.GetInstance: TSingleton; begin EnterCriticalSection(FCriticalSection); try if FSingleton = nil then begin FSingleton := TSingleton.CreateInstance; end; finally LeaveCriticalSection(FCriticalSection); end; Result := FSingleton; end; end.
最後に事前初期化版です。
unit Unit16; interface uses SysUtils, Windows; type TSingleton = class(TObject) private FTestValue: Integer; class var FSingleton: TSingleton; constructor CreateInstance; public class constructor Create; class destructor Destroy; constructor Create; destructor Destroy; override; class function GetInstance: TSingleton; property TestValue: Integer read FTestValue write FTestValue; end; ECreateSingleton = class(Exception) end; implementation { TSingleton } class constructor TSingleton.Create; begin FSingleton := TSingleton.CreateInstance; end; class destructor TSingleton.Destroy; begin FSingleton.Free; end; constructor TSingleton.Create; begin raise ECreateSingleton.Create('TSingleton.Create cannot use.'); end; constructor TSingleton.CreateInstance; begin inherited Create; { Initialize } FTestValue := 0; end; destructor TSingleton.Destroy; begin { Finalize } inherited; end; class function TSingleton.GetInstance: TSingleton; begin Result := FSingleton; end; end.
プロジェクト内でTSingletonを使用していない場合、TSingleton関係のコードがリンクされないことがわかります。
0 件のコメント:
コメントを投稿