我知道这在社区的各个地方都被讨论了很多次,但我在Delphi中找不到一个简单的单例模式实现.我在C#中有一个例子:
public sealed class Singleton {
// Private Constructor
Singleton( ) { }
// Private object instantiated with private constructor
static readonly Singleton instance = new Singleton( );
// Public static property to get the object
public static Singleton UniqueInstance {
get { return instance;}
}
Run Code Online (Sandbox Code Playgroud)
我知道在Delphi中没有像这样优雅的解决方案,我看到很多关于无法在Delphi中正确隐藏构造函数的讨论(使其成为私有),因此我们需要覆盖NewInstance和FreeInstrance方法.我相信这是我在http://ibeblog.com/?p=65上找到的实现:
type
TTestClass = class
private
class var FInstance: TTestClass;
public
class function GetInstance: TTestClass;
class destructor DestroyClass;
end;
{ TTestClass }
class destructor TTestClass.DestroyClass;
begin
if Assigned(FInstance) then
FInstance.Free;
end;
class …Run Code Online (Sandbox Code Playgroud) Delphi是否在对象完全构造之前分配了一个实例变量?
换句话说,给定一个变量:
var
customer: TCustomer = nil;
Run Code Online (Sandbox Code Playgroud)
然后我们构建一个客户并将其分配给变量:
customer := TCustomer.Create;
Run Code Online (Sandbox Code Playgroud)
是否可能customer不是nil,但不是指向完全构造TCustomer?
执行延迟初始化时,这会成为一个问题:
function SacrifialCustomer: TCustomer;
begin
if (customer = nil) then
begin
criticalSection.Enter;
try
customer := TCustomer.Create;
finally
criticalSection.Leave;
end;
end;
Result := customer;
end;
Run Code Online (Sandbox Code Playgroud)
错误在于:
if (customer = nil)
Run Code Online (Sandbox Code Playgroud)
另一个线程可能会调用:
customer := TCustomer.Create;
Run Code Online (Sandbox Code Playgroud)
并且在构造发生之前为变量赋值.这会导致线程假定这customer是一个有效的对象,因为该变量已分配.
这个多线程单例错误可以在Delphi(5)中发生吗?
奖金问题
Delphi 是否有可接受的,线程安全的一次性初始化设计模式?许多人通过覆盖而在德尔福实施了单身人士 ; 他们的实现将在多个线程中失败.NewInstanceFreeInstance
严格来说,我不是在回答如何实现和单例,而是懒惰初始化.虽然单例可以使用延迟初始化,但是懒惰初始化不限于单例.
更新 …