如何将DRY应用于涉及Form组件的接口实现



我有一个接口IComm声明一个例程SetMonitorLogLevel():

unit IFaceComm;
interface
type
  TMonitorLogLevel = (mllOnlyImportant, mllAll);
  IComm = Interface(IInterface)
    procedure SetMonitorLogLevel(LogLevel: TMonitorLogLevel);
  end;
end.

接口是由两个窗体实现的,它们彼此相似,frmBarCommfrmFooComm,看起来像这样:

TfrmBarComm = class(TForm, IFaceComm.IComm)
  cboDebugLevel: TComboBox;
private
  procedure SetMonitorLogLevel(LogLevel: IFaceComm.TMonitorLogLevel);
end;

请注意,这两个表单有很多共同的组件,比如cboDebugLevel,但也可以有其他表单没有的组件。

两个窗体在中实现IComm.SetMonitorLogLevel()的方式完全相同:

procedure TfrmBarComm.SetMonitorLogLevel(LogLevel: IFaceComm.TMonitorLogLevel);
begin
  case LogLevel of
    IFaceComm.TMonitorLogLevel.mllOnlyImportant:
      Self.cboDebugLevel.ItemIndex := 0;
    IFaceComm.TMonitorLogLevel.mllAll:
      Self.cboDebugLevel.ItemIndex := 1;
  end;
end;

我如何避免违反Don't Repeat Yourself (DRY)原则?我经常遇到这个问题,当复制粘贴例程比我上面展示的简单示例大得多时,情况就特别糟糕了。

通常的处理方法是创建另一个实现接口的类。它可能看起来像这样:

type
  TComboBoxCommImplementor = class(TInterfacedObject, IFaceComm.IComm)
  private
    FDebugLevel: TComboBox;
  public
    constructor Create(DebugLevel: TComboBox);
    procedure SetMonitorLogLevel(LogLevel: TMonitorLogLevel);
  end;
constructor TComboBoxCommImplementor.Create(DebugLevel: TComboBox);
begin
  inherited Create;
  FDebugLevel := DebugLevel;
end;
procedure TComboBoxCommImplementor.SetMonitorLogLevel(
  LogLevel: IFaceComm.TMonitorLogLevel);
begin
  case LogLevel of
    IFaceComm.TMonitorLogLevel.mllOnlyImportant:
      FDebugLevel.ItemIndex := 0;
    IFaceComm.TMonitorLogLevel.mllAll:
      FDebugLevel.ItemIndex := 1;
  end;
end;

然后在表单中使用委托实现接口:

type
  TfrmBarComm = class(TForm, IFaceComm.IComm)
    cboDebugLevel: TComboBox;
  private
    FComm: IFaceComm.IComm;
    property Comm: IFaceComm.IComm read FComm implements IFaceComm.IComm
  public
    constructor Create(AOwner: TComponent); override;
  end;
constructor TfrmBarComm.Create(AOwner: TComponent);
begin
  inherited;
  FComm := TComboBoxCommImplementor.Create(cboDebugLevel);
end;

创建一个拥有两个窗体上使用的组件的框架。帧实现IComm。使用框架的两种表单和两种表单都实现了IComm。框架可以作为委托接口实现的属性访问。

它看起来像这样:

type TfrmBarComm = class(TForm)
  FFrameComm: TFrameComm;
public
  property FrameComm: TFrameComm read FFrameComm implements IComm;
end;

相关内容

最新更新