gpt4 book ai didi

delphi - 通用工厂

转载 作者:行者123 更新时间:2023-12-03 18:00:28 25 4
gpt4 key购买 nike

假设我有一个 TModel:

TModelClass = class of TModel;
TModel = class
procedure DoSomeStuff;
end;

和 2 个后代:

TModel_A = class(TModel);
TModel_B = class(TModel);

还有一个工厂:

TModelFactory = class
class function CreateModel_A: TModel_A;
class function CreateModel_B: TModel_B;
end;

现在我想重构一下:

TModelFactory = class
class function CreateGenericModel(Model: TModelClass) : TModel
end;

class function TModelFactory.CreateGenericModel(Model: TModelClass) : TModel
begin
...
case Model of
TModel_A: Result := TModel_A.Create;
TModel_B: Result := TModel_B.Create;
end;
...
end;

到目前为止一切正常,但每次我创建一个 TModel后代,我要修改工厂case声明。

我的问题:是否可以为我所有的 TModel 创建一个 100% 通用的工厂?后代,所以每次我创建一个TModel我不必修改后代 TModelFactory

我尝试使用 Delphi 2009 泛型但没有找到有值(value)的信息,所有信息都与 TList<T> 的基本用法有关等等。

更新对不起,但也许我不清楚或不明白你的回答(我还是个菜鸟),但我想要实现的是:

var
M: TModel_A;
begin
M: TModelFactory.CreateGenericModel(MY_CONCRETE_CLASS);

最佳答案

好吧,你可以写

class function TModelFactory.CreateGenericModel(AModelClass: TModelClass): TModel;
begin
Result := AModelClass.Create;
end;

但是你不再需要工厂了。通常会有一个不同类型的选择器,如整数或字符串 ID,以选择工厂应创建的具体类。

编辑:

为了回答您关于如何在无需更改工厂的情况下添加新类的评论 - 我将为您提供一些适用于非常旧的 Delphi 版本的简单示例代码,Delphi 2009 应该提供更好的方法来执行此操作。

每个新的后代类只需要向工厂注册。可以使用多个 ID 注册同一类。该代码使用字符串 ID,但整数或 GUID 也同样有效。

type
TModelFactory = class
public
class function CreateModelFromID(const AID: string): TModel;
class function FindModelClassForId(const AID: string): TModelClass;
class function GetModelClassID(AModelClass: TModelClass): string;
class procedure RegisterModelClass(const AID: string;
AModelClass: TModelClass);
end;

{ TModelFactory }

type
TModelClassRegistration = record
ID: string;
ModelClass: TModelClass;
end;

var
RegisteredModelClasses: array of TModelClassRegistration;

class function TModelFactory.CreateModelFromID(const AID: string): TModel;
var
ModelClass: TModelClass;
begin
ModelClass := FindModelClassForId(AID);
if ModelClass <> nil then
Result := ModelClass.Create
else
Result := nil;
end;

class function TModelFactory.FindModelClassForId(
const AID: string): TModelClass;
var
i, Len: integer;
begin
Result := nil;
Len := Length(RegisteredModelClasses);
for i := 0 to Len - 1 do
if RegisteredModelClasses[i].ID = AID then begin
Result := RegisteredModelClasses[i].ModelClass;
break;
end;
end;

class function TModelFactory.GetModelClassID(AModelClass: TModelClass): string;
var
i, Len: integer;
begin
Result := '';
Len := Length(RegisteredModelClasses);
for i := 0 to Len - 1 do
if RegisteredModelClasses[i].ModelClass = AModelClass then begin
Result := RegisteredModelClasses[i].ID;
break;
end;
end;

class procedure TModelFactory.RegisterModelClass(const AID: string;
AModelClass: TModelClass);
var
i, Len: integer;
begin
Assert(AModelClass <> nil);
Len := Length(RegisteredModelClasses);
for i := 0 to Len - 1 do
if (RegisteredModelClasses[i].ID = AID)
and (RegisteredModelClasses[i].ModelClass = AModelClass)
then begin
Assert(FALSE);
exit;
end;
SetLength(RegisteredModelClasses, Len + 1);
RegisteredModelClasses[Len].ID := AID;
RegisteredModelClasses[Len].ModelClass := AModelClass;
end;

关于delphi - 通用工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1103607/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com