如何用TForm后代的泛型实现Singleton模式?

时间:2014-05-11 11:23:17

标签: delphi generics design-patterns singleton delphi-2010

我希望使用泛型功能在Delphi 2010中实现Singleton模式。

type
  TgrsObj = class
     class function Singleton<T: class, constructor>(O: T): T; static;
  end;


class function TgrsObj.Singleton<T>(O: T): T;
begin
   if O = nil then
     O := T.Create;
   Result := O;
end;

我想称之为:

var
  test: TTestClass;

...
test := TgrsObj<TTestClass>(test);

我的方法可行吗?我应该纠正什么才能让它发挥作用?

老实说,我最后的任务是通过TForm后代实现Singleton模式,将所需的形式作为单身。

这是下一步,但现在我对泛型的CONSTRUCTOR约束有疑问。它需要一个类来拥有一个没有参数的构造函数。但是TForm没有它......什么是变通方法?

1 个答案:

答案 0 :(得分:3)

在我看来,Delphi中的constructor约束几乎没用。它并没有真正使用,因为你需要创建TForm后代,并且它们有一个接收参数的构造函数。

您应该将通用类型T限制为从TForm派生。

type
  TgrsObj = class
    class function Singleton<T: TForm>(O: T): T; static;
  end;

然后实施:

class function TgrsObj.Singleton<T>(O: T): T;
begin
   Result := O;
   if not Assigned(Result) then
     Result := T(TFormClass(T).Create(nil));
end;

由于您实际上只是尝试访问虚拟TComponent构造函数,因此可以使类更加通用:

type
  TgrsObj = class
    class function Singleton<T: TComponent>(O: T): T; static;
  end;

class function TgrsObj.Singleton<T>(O: T): T;
begin
   Result := O;
   if not Assigned(Result) then
     Result := T(TComponentClass(T).Create(nil));
end;

当然,这会强制nil作为表单实例的所有者。您可能希望更改方法以接收所有者,然后可以将其传递给构造函数。