在Delphi2010里面整了个单例模式,大家看看好用不?该如何处理
在Delphi2010里面整了个单例模式,大家看看好用不?
------解决方案--------------------
单例模式是什么?
------解决方案--------------------
至少编译能通过
------解决方案--------------------
没有什么实际用途啊,至少得在类中加一个容器类吧,还要支持多线程安全访问。
而且,你的类最终没法创建实例啊!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
(* * 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;