在Delphi2010里面整了个单例模式,大家看看好用不?该如何处理

在Delphi2010里面整了个单例模式,大家看看好用不?
Delphi(Pascal) code

(*
 *  This unit demonstrates how to implement the Singleton Pattern in Delphi 2010.
 *  The final reversion will be available in the Delphi Spring Framework.
 *  
 *  Zuo Baoquan
 *
 *)

unit SingletonPatternUnit;

interface

type
  /// <summary>
  /// Provides a simple, fast and thread-safe Singleton Pattern implementation.
  /// </summary>
  /// <description>
  /// Singleton Pattern is defined as:
  /// Ensure a class only has one instance, and provide a global point of access to it.
  /// </description>
  /// <remarks>
  /// 1. Use Instance class property to get the singleton instance.
  /// 2. Concrete Singleton Classes may override DoCreate/DoDestroy if necessary.
  /// 3. Do not call Create/Free methods, otherwise an EInvalidOp exception will be raised.
  /// </remarks>
  /// <example>
  /// <code>
  ///   TApplicationContext = class(TSingleton<TApplicationContext>)
  ///   protected
  ///     procedure DoCreate; override;
  ///     procedure DoDestroy; override;
  ///   end;
  /// </code>
  /// </example>
  /// <author>Zuo Baoquan (Paul)</author>
  TSingleton<T: class> = class //(TInterfaceBase)
  strict private
    class var fInstance: T;
    class function GetInstance: T; static;
    class destructor Destroy;
  protected
    procedure DoCreate; virtual;
    procedure DoDestroy; virtual;
  public
    constructor Create;
    destructor Destroy; override;
    class property Instance: T read GetInstance;
  end;

implementation

uses
  Windows, SysUtils;

{$REGION 'TSingleton<T>'}

class destructor TSingleton<T>.Destroy;
begin
  if fInstance <> nil then
  begin
    TSingleton<T>(fInstance).DoDestroy;
    TSingleton<T>(fInstance).FreeInstance;
    fInstance := nil;
  end;
end;

constructor TSingleton<T>.Create;
begin
  raise EInvalidOp.Create('Use Instance class property instead.');
end;

destructor TSingleton<T>.Destroy;
begin
  if ExceptObject = nil then
    raise EInvalidOp.Create('Free/Destroy.');
end;

class function TSingleton<T>.GetInstance: T;
var
  obj: T;
begin
  if fInstance = nil then
  begin
    obj := T(T.NewInstance);
    TSingleton<T>(obj).DoCreate;
    if InterlockedCompareExchangePointer(PPointer(@fInstance)^, PPointer(@obj)^, nil) <> nil then
    begin
      TSingleton<T>(obj).DoDestroy;
      TSingleton<T>(obj).FreeInstance;
    end;
  end;
  Result := fInstance;
end;

procedure TSingleton<T>.DoCreate;
begin
end;

procedure TSingleton<T>.DoDestroy;
begin
end;

{$ENDREGION}

end.





------解决方案--------------------
单例模式是什么?
------解决方案--------------------
至少编译能通过

------解决方案--------------------
没有什么实际用途啊,至少得在类中加一个容器类吧,还要支持多线程安全访问。

而且,你的类最终没法创建实例啊!Create要产生异常;访问Instance更不通,实例都没有被创建,如何能够访问Instance属性喃?形成悖论了。

------解决方案--------------------
先把Create放到protected部分,然后在单元文件中增加initialization和finalization,在这两部分中创建类实例,这样大概可行。


------解决方案--------------------
up,僵哥出声了
------解决方案--------------------
这样比较清晰一些:比如声明一个基类 TBaseSingleton,继承 NewInstance/FreeInstance,让对象不能手动创建和释放对象,而是另外提供 protected 方法负责创建和销毁。提供一个管理类,用一个 class var list 之类维护 TBaseSingleton 的继承类和其实例的对应关系,然后提供一个 class function GetInstance<T: TSingleton>: T 方法,在这里负责创建并考虑线程安全就可以了,就像这样:
Delphi(Pascal) code

  TBaseSingleton  = class abstract
  private
    class function yourNewInstance: TObject;
    procedure yourFreeInstance;  // 别忘了 BeforeDestruction
  protected
    constructor DoCreate; virtual; abstract; // must be overrided
    procedure DoDestroy; virtual;
  public
    class function NewInstance: TObject; override; // raise an exception
    procedure FreeInstance; override; // raise an exception
  end;
  TSingletonClass = class of TBaseSingleton;

  Tfoo = class
  private
    class var
      FDict: TDictionary<TSingletonClass, TBaseSingleton>;
      FCS: TRTLCriticalSection;
  public
    class constructor Create;
    class destructor Destroy;
    class function GetInstance<T: TBaseSingleton>: T;
    {
      EnterCriticalSection(FCS);
      try
        if(FDict.TryGetValue(TSingletonClass(T), TBaseSingleton(Result)))then Exit;
        Result  := T(TSingletonClass(T).yourNewInstance);
        FDict.Add(TSingletonClass(T), TBaseSingleton(Result));
      finally
        LeaveCriticalSection(FCS);
      end;
      TBaseSingleton(Result).DoCreate;
    }
  end;