delphi – 如何链接“并行”类层次结构?
发布时间:2020-12-15 09:23:43 所属栏目:大数据 来源:网络整理
导读:我有一个小类层次结构,其中每个类对应于某个TComponent后代(比如基类TDefaultFrobber与后代TActionFrobber和TMenuItemFrobber,分别对应于TComponent,TCustomAction和TMenuItem).现在我想要一个像这样的工厂(?)函数: function CreateFrobber(AComponent: TC
我有一个小类层次结构,其中每个类对应于某个TComponent后代(比如基类TDefaultFrobber与后代TActionFrobber和TMenuItemFrobber,分别对应于TComponent,TCustomAction和TMenuItem).现在我想要一个像这样的工厂(?)函数:
function CreateFrobber(AComponent: TComponent): IFrobber; begin if AComponent is TCustomAction then Result := TActionFrobber.Create(TCustomAction(AComponent)) else if AComponent is TMenuItem then Result := TMenuItemFrobber.Create(TMenuItem(AComponent)) else Result := TDefaultFrobber.Create(AComponent); end; 我可以以某种方式重构这个以使用虚函数或类似的东西而不是if-else级联或RTTI吗? 编辑:我现在的解决方案: unit Frobbers; interface uses Classes; type IComponentFrobber = interface end; TComponentFrobberClass = class of TComponentFrobber; TComponentFrobber = class(TInterfacedObject,IComponentFrobber) strict private FComponent: TComponent; protected constructor Create(AComponent: TComponent); property Component: TComponent read FComponent; public class function FindFrobberClass(AComponentClass: TComponentClass): TComponentFrobberClass; overload; static; class function FindFrobberClass(AComponent: TComponent): TComponentFrobberClass; overload; static; class procedure RegisterFrobber(AComponentClass: TComponentClass; AFrobberClass: TComponentFrobberClass); static; end; implementation uses ActnList,Menus; type TComponentFrobberRegistryItem = record ComponentClass: TComponentClass; FrobberClass: TComponentFrobberClass; end; var FComponentFrobberRegistry: array of TComponentFrobberRegistryItem; class function TComponentFrobber.FindFrobberClass(AComponentClass: TComponentClass): TComponentFrobberClass; var i: Integer; begin // Search backwards,so that more specialized frobbers are found first: for i := High(FComponentFrobberRegistry) downto Low(FComponentFrobberRegistry) do if FComponentFrobberRegistry[i].ComponentClass = AComponentClass then begin Result := FComponentFrobberRegistry[i].FrobberClass; Exit; end; Result := nil; end; constructor TComponentFrobber.Create(AComponent: TComponent); begin inherited Create; FComponent := AComponent; end; class function TComponentFrobber.FindFrobberClass(AComponent: TComponent): TComponentFrobberClass; var i: Integer; begin // Search backwards,so that more specialized frobbers are found first: for i := High(FComponentFrobberRegistry) downto Low(FComponentFrobberRegistry) do if AComponent is FComponentFrobberRegistry[i].ComponentClass then begin Result := FComponentFrobberRegistry[i].FrobberClass; Exit; end; Result := nil; end; class procedure TComponentFrobber.RegisterFrobber(AComponentClass: TComponentClass; AFrobberClass: TComponentFrobberClass); var i: Integer; begin Assert(FindFrobberClass(AComponentClass) = nil,'Duplicate Frobber class'); i := Length(FComponentFrobberRegistry); SetLength(FComponentFrobberRegistry,Succ(i)); FComponentFrobberRegistry[i].ComponentClass := AComponentClass; FComponentFrobberRegistry[i].FrobberClass := AFrobberClass; end; function CreateComponentFrobber(AComponent: TComponent): IComponentFrobber; var FrobberClass: TComponentFrobberClass; begin FrobberClass := TComponentFrobber.FindFrobberClass(AComponent); Assert(FrobberClass <> nil); Result := FrobberClass.Create(AComponent); end; type TActionFrobber = class(TComponentFrobber); TMenuItemFrobber = class(TComponentFrobber); initialization TComponentFrobber.RegisterFrobber(TCustomAction,TActionFrobber); TComponentFrobber.RegisterFrobber(TMenuItem,TMenuItemFrobber); end. 感谢Cesar,Gamecat和mghie. 解决方法
2意见建议:
创建类对数组,然后就可以得到索引并使用类构造函数对, var ArrayItem: array[0..1] of TComponentClass = (TActionFrobber,TMenuItemFrobber); ArrayOwner: array[0..1] of TComponentClass = (TCustomAction,TMenuItem); function CreateFrobber(AComponent: TComponentClass): IFrobber; var Index: Integer; begin Result:= nil; for I := Low(ArrayOwner) to High(ArrayOwner) do if AComponent is ArrayOwner[I] then begin Result:= ArrayItem[I].Create(AComponent); Break; end; if Result = nil then Result:= TDefaultFrobber.Create(AComponent); end; 或使用RTTI ClassName约定,如下所示: function CreateFrobber(AComponent: TComponentClass): IFrobber; const FrobberClassSuffix = 'Frobber'; var LClass: TComponentClass; LComponent: TComponent; begin LClass:= Classes.FindClass(AComponent.ClassName + FrobberClassSuffix); if LClass <> nil then LComponent:= LClass.Create(AComponent) else LComponent:= TDefaultFrobber.Create(AComponent); if not Supports(LComponent,IFrobber,Result) then Result:= nil; end; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |