将引用/一个位置中的对象传递给样式对象

时间:2011-03-25 19:55:29

标签: delphi object pass-by-reference

我有一个很大的应用程序,目前正在设计。 为了节省我更改IDE / Object Inspector中的所有按钮,我计划为主要对象执行一些功能,例如

procedure StyleButton(AButton : TButton)
begin
    AButton.Color := clGreen;
    AButton.Font.Style = [fsBold];
end;

等等,然后根据需要将其添加到表单onCreates

StyleButton(Button1); whatever etc

在这样的参数中传递对象没有问题。它只引用第一个对象吗?

它工作正常,我想不出任何问题,但因为这是一个大型应用程序,我只想确保没有问题/内存泄漏/资源消耗问题的数千名用户。

也将使用TAdvStringGrid和TEdit / TMemo组件做类似的事情。

然后只允许1个地方更改这些设置。

或者有人有更好的主意?

4 个答案:

答案 0 :(得分:6)

这是一个很好的主意。该函数将修改传递给它的任何对象。

您没有通过引用传递。你正在经历价值。您传递的值引用。 “通过引用传递”表示您使用varout个关键字,在这种情况下,是适当的。

答案 1 :(得分:4)

你的想法很好,正如其他回答者已经说过的那样。只是想提出一个比David更远的解决方案以及你可能想要考虑的事情,以避免添加许多语句,如:

StyleButton(Button1);
StyleButton(Button2);

每个表格都适用于您想要设计的每个控件;

我建议的是添加一个方法调用,例如每个表单的OnShow事件:

procedure TForm1.FormShow(Sender: TObject);
begin
  TStyler.StyleForm(Self);
end;

TStyler可以在一个单独的单元中实现,如下所示:

interface

type
  TStyler = class;
  TStylerClass = class of TStyler;

  TStyler = class(TObject)
  public
    class procedure StyleForm(const aForm: TCustomForm);
    class procedure StyleControl(const aControl: TControl); virtual;
    class function GetStyler(const aControl: TControl): TStylerClass;
  end;

implementation

uses
  Contnrs;

type
  TButtonStyler = class(TStyler)
  public
    class procedure StyleControl(const aControl: TControl); override;
  end;

  TEditStyler = class(TStyler)
  public
    class procedure StyleControl(const aControl: TControl); override;
  end;

  TLabelStyler = class(TStyler)
  public
    class procedure StyleControl(const aControl: TControl); override;
  end;

var
  _Controls: TClassList;
  _Stylers: TClassList;

{ TStyler }

class function TStyler.GetStyler(const aControl: TControl): TStylerClass;
var
  idx: Integer;
begin
  Result := TStyler;
  idx := _Controls.IndexOf(aControl.ClassType);
  if idx > -1 then
    Result := TStylerClass(_Stylers[idx]);
end;

class procedure TStyler.StyleForm(const aForm: TCustomForm);

  procedure _StyleControl(const aControl: TControl);
  var
    i: Integer;
    StylerClass: TStylerClass;
  begin
    StylerClass := TStyler.GetStyler(aControl);
    StylerClass.StyleControl(aControl);
    if (aControl is TWinControl) then
      for i := 0 to TWinControl(aControl).ControlCount - 1 do
        _StyleControl(TWinControl(aControl).Controls[i]);
  end;

var
  i: Integer;
begin
  _StyleControl(aForm);
end;

class procedure TStyler.StyleControl(const aControl: TControl);
begin
// Do nothing. This is a catch all for all controls that do not need specific styling.
end;

{ TButtonStyler }

class procedure TButtonStyler.StyleControl(const aControl: TControl);
begin
  inherited;
  if aControl is TButton then
  begin
    TButton(aControl).Font.Color := clRed;
    TButton(aControl).Font.Style := [fsBold];
  end;
end;

{ TEditStyler }

class procedure TEditStyler.StyleControl(const aControl: TControl);
begin
  inherited;
  if aControl is TEdit then
  begin
    TEdit(aControl).Color := clGreen;
  end;
end;

{ TLabelStyler }

class procedure TLabelStyler.StyleControl(const aControl: TControl);
begin
  inherited;
  if aControl is TLabel then
  begin
    TLabel(aControl).Font.Color := clPurple;
    TLabel(aControl).Font.Style := [fsItalic];
  end;
end;

initialization
  _Controls := TClassList.Create;
  _Stylers := TClassList.Create;

  _Controls.Add(TButton);
  _Stylers.Add(TButtonStyler);

  _Controls.Add(TEdit);
  _Stylers.Add(TEditStyler);

  _Controls.Add(TLabel);
  _Stylers.Add(TLabelStyler);

finalization
  FreeAndNiL(_Controls);
  FreeAndNiL(_Stylers);
end.

此解决方案基本上使用多态和将控件类链接到样式器类的注册表。它还使用类过程和函数来避免必须实例化任何东西。

请注意,注册表在此示例中实现为需要手动保持同步的两个列表,因为代码假定在索引X处查找类将在另一个列表中的相同索引处找到样式器。这当然可以在很大程度上得到改善,但这足以说明这个概念。

答案 2 :(得分:2)

不,没有问题(在您的特定情况下)将对象作为参数传递

procedure StyleButton(AButton : TButton)

当你这样做时,你传递一个地址存储器(引用)并设置引用对象的一些属性,所以没有问题。

答案 3 :(得分:2)

要添加Rob和RRUZ已经说过的内容,您可以考虑使用开放数组参数的额外帮助器:

procedure StyleButtons(const Buttons: array of TButton);
var
  i: Integer;
begin
  for i := low(Buttons) to high(Buttons) do
    StyleButton(Buttons[i]);
end;

然后您可以将其称为:

StyleButtons([btnOK, btnCancel, btnRelease64bitDelphi]);
在我看来,

在电话会议上比以下更具可读性:

StyleButton(btnOK);
StyleButton(btnCancel);
StyleButton(btnRelease64bitDelphi);

请注意,我将open数组作为const参数传递,因为在处理数组时更有效。因为数组的每个元素本身都是对按钮的引用,所以您可以修改实际按钮。 const只表示您无法更改引用。