You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不使用类助手,用多态或设计模式优雅处理外部库TPasElement派生类?

实现方案

以下三种方案均不需要修改外部类库代码、不使用类助手,可直接替换原有的分支判断逻辑。


方案1:类型字典映射法(适用于Delphi XE及以上版本)

利用泛型字典存储子类对应的处理逻辑,运行时直接通过类类型匹配对应处理方法,代码最简洁。

uses
  System.Generics.Collections, System.SysUtils;

var
  // 字典键为子类类型,值为对应处理逻辑的匿名方法
  ProcessHandlers: TDictionary<TClass, TProc<TPasElement>>;

// 程序启动时初始化一次即可
procedure InitProcessHandlers;
begin
  ProcessHandlers := TDictionary<TClass, TProc<TPasElement>>.Create;
  ProcessHandlers.Add(TPasConst,
    procedure(E: TPasElement)
    begin
      Writeln(TPasConst(E).ConstInfo);
    end);
  ProcessHandlers.Add(TPasVariable,
    procedure(E: TPasElement)
    begin
      Writeln(TPasVariable(E).VariableInfo);
    end);
  ProcessHandlers.Add(TPasType,
    procedure(E: TPasElement)
    begin
      Writeln(TPasType(E).TypeInfo);
    end);
  ProcessHandlers.Add(TPasProperty,
    procedure(E: TPasElement)
    begin
      Writeln(TPasProperty(E).PropertyInfo);
    end);
  ProcessHandlers.Add(TPasProcedure,
    procedure(E: TPasElement)
    begin
      Writeln(TPasProcedure(E).ProcedureInfo);
    end);
end;

// 最终调用的处理方法
procedure Process(Element: TPasElement);
var
  Handler: TProc<TPasElement>;
begin
  if not Assigned(Element) then Exit;
  if ProcessHandlers.TryGetValue(Element.ClassType, Handler) then
    Handler(Element);
end;
  • 优点:无冗余类型判断,新增子类支持仅需新增一行字典注册逻辑,代码量最少
  • 缺点:需要Delphi版本支持匿名方法,更适合单一处理逻辑的场景

方案2:包装类继承多态方案(全版本兼容)

自定义一套包装类继承体系,通过多态特性实现逻辑分发,兼容所有Delphi版本。

// 包装类基类
type
  TElementWrapper = class abstract
  protected
    FElement: TPasElement;
  public
    constructor Create(AElement: TPasElement);
    procedure Process; virtual; abstract;
  end;

  // 各子类对应的包装类
  TConstWrapper = class(TElementWrapper)
  public
    procedure Process; override;
  end;
  TVariableWrapper = class(TElementWrapper)
  public
    procedure Process; override;
  end;
  TTypeWrapper = class(TElementWrapper)
  public
    procedure Process; override;
  end;
  TPropertyWrapper = class(TElementWrapper)
  public
    procedure Process; override;
  end;
  TProcedureWrapper = class(TElementWrapper)
  public
    procedure Process; override;
  end;

// 工厂函数:根据传入的元素返回对应包装类实例
function CreateElementWrapper(AElement: TPasElement): TElementWrapper;
begin
  Result := nil;
  if not Assigned(AElement) then Exit;
  if AElement is TPasConst then
    Result := TConstWrapper.Create(AElement)
  else if AElement is TPasVariable then
    Result := TVariableWrapper.Create(AElement)
  else if AElement is TPasType then
    Result := TTypeWrapper.Create(AElement)
  else if AElement is TPasProperty then
    Result := TPropertyWrapper.Create(AElement)
  else if AElement is TPasProcedure then
    Result := TProcedureWrapper.Create(AElement);
end;

// 包装类实现
constructor TElementWrapper.Create(AElement: TPasElement);
begin
  inherited Create;
  FElement := AElement;
end;

procedure TConstWrapper.Process;
begin
  Writeln(TPasConst(FElement).ConstInfo);
end;

procedure TVariableWrapper.Process;
begin
  Writeln(TPasVariable(FElement).VariableInfo);
end;

procedure TTypeWrapper.Process;
begin
  Writeln(TPasType(FElement).TypeInfo);
end;

procedure TPropertyWrapper.Process;
begin
  Writeln(TPasProperty(FElement).PropertyInfo);
end;

procedure TProcedureWrapper.Process;
begin
  Writeln(TPasProcedure(FElement).ProcedureInfo);
end;

// 最终调用的处理方法
procedure Process(Element: TPasElement);
var
  Wrapper: TElementWrapper;
begin
  Wrapper := CreateElementWrapper(Element);
  if Assigned(Wrapper) then
  try
    Wrapper.Process;
  finally
    Wrapper.Free;
  end;
end;
  • 优点:完全符合面向对象多态设计,兼容所有Delphi版本,后续新增处理逻辑仅需在包装类中新增虚方法即可
  • 缺点:需要额外定义一套包装类,类型判断逻辑收敛在工厂函数中,仅需修改一次

方案3:访问者模式(适合多处理逻辑场景)

如果需要对元素做多种不同处理(比如打印、导出XML、统计信息等),用访问者模式可以做到新增处理逻辑不修改原有代码。

// 访问者基类
type
  TElementVisitor = class abstract
  public
    procedure VisitConst(Element: TPasConst); virtual; abstract;
    procedure VisitVariable(Element: TPasVariable); virtual; abstract;
    procedure VisitType(Element: TPasType); virtual; abstract;
    procedure VisitProperty(Element: TPasProperty); virtual; abstract;
    procedure VisitProcedure(Element: TPasProcedure); virtual; abstract;
    // 调度方法,统一做类型判断
    procedure Dispatch(Element: TPasElement);
  end;

// 具体的打印处理访问者
type
  TPrintVisitor = class(TElementVisitor)
  public
    procedure VisitConst(Element: TPasConst); override;
    procedure VisitVariable(Element: TPasVariable); override;
    procedure VisitType(Element: TPasType); override;
    procedure VisitProperty(Element: TPasProperty); override;
    procedure VisitProcedure(Element: TPasProcedure); override;
  end;

procedure TElementVisitor.Dispatch(Element: TPasElement);
begin
  if Element is TPasConst then
    VisitConst(TPasConst(Element))
  else if Element is TPasVariable then
    VisitVariable(TPasVariable(Element))
  else if Element is TPasType then
    VisitType(TPasType(Element))
  else if Element is TPasProperty then
    VisitProperty(TPasProperty(Element))
  else if Element is TPasProcedure then
    VisitProcedure(TPasProcedure(Element));
end;

// 打印访问者逻辑实现
procedure TPrintVisitor.VisitConst(Element: TPasConst);
begin
  Writeln(Element.ConstInfo);
end;

procedure TPrintVisitor.VisitVariable(Element: TPasVariable);
begin
  Writeln(Element.VariableInfo);
end;

procedure TPrintVisitor.VisitType(Element: TPasType);
begin
  Writeln(Element.TypeInfo);
end;

procedure TPrintVisitor.VisitProperty(Element: TPasProperty);
begin
  Writeln(Element.PropertyInfo);
end;

procedure TPrintVisitor.VisitProcedure(Element: TPasProcedure);
begin
  Writeln(Element.ProcedureInfo);
end;

// 最终调用的处理方法
procedure Process(Element: TPasElement);
var
  Visitor: TPrintVisitor;
begin
  Visitor := TPrintVisitor.Create;
  try
    Visitor.Dispatch(Element);
  finally
    Visitor.Free;
  end;
end;
  • 优点:扩展性极强,新增处理逻辑仅需新增访问者子类,不需要修改原有调度逻辑
  • 缺点:结构相对复杂,适合处理逻辑较多的中大型项目

内容的提问来源于stack exchange,提问作者simone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 19:15:03