Delmo
Delmo

Reputation: 2276

How to reuse the same TInterfacedObject instance on the same scope in Delphi

I have implemented a bitmap adapter to extent bitmap functionality as follow:

unit UBitmapHelper;

IBmpUtils = interface
  procedure SomeNewRoutine;
end;

TBitmapUtilsAdapter = class (TInterfacedObject, IBmpUtils)
public
  constructor Create (ABitmap: TBitmap);
  //IBmpUtils
  procedure SomeNewRoutine;
end;

TBitmapHelper = class helper for TBitmap
  function Utils: IBmpUtils; //method factory pattern
end;

function TBitmapHelper.Utils: IBmpUtils;
begin
  Result := TBitmapUtilsAdapter.Create(Self);
end;

so I now can use this adapter as follow:

uses UBitmapHelper;

procedure Test;  
var
  MyBitmap: TBitmap;
  i: Integer;
begin
  MyBitmap := TBitmap.Create;
  MyBitmap.SetSize(50, 50);
  for i := 1 to 100 do
    MyBitmap.Utils.SomeNewRoutine;
  FreeAndNil(MyBitmap);  
end;

I don't need to free Utils as my adapter inherited from TInterfacedObject so it will be automatically freed when go out Test procedure scope, fine! but maybe there is a little performance problem.

Does the compiler create a new Utils instance for each iteration or it is smart enough in this case to reuse the same Utils instance while it's in the same scope?

Obviously I can get the instance before the for-loop then use it inside but I am trying to find out how to use the notation MyBitmap.Utils.SomeNewRoutine anywhere without a big deal with performance. Is any way to do it?

Note: I am using Delphi 10.3

Edit

To be more clear:

  1. I am enforced to implement IBmpUtils interface so I can't use neither record nor helper classes. I am also enforced not to create my own TBitmap descendent class then implement the IBmpUtils interface so my only solution would be the adapter.
  2. I want to keep all utilities under a "namespace", e.g. MyBitmap.Utils.SomeNewRoutine.
  3. I want to use the "notation" MyBitmap.Utils.XYZ everywhere without worry about create/destroy instances.

Is there any way to accomplish this without a performance penalty like one described above (i.e use the notation inside a loop)?

Upvotes: 1

Views: 103

Answers (1)

Andreas Rejbrand
Andreas Rejbrand

Reputation: 109003

In the comments, it turns out that the main goal is to be able to write things like bm.Utils.SomeProcA, bm.Utils.SomeProcB for every TBitmap value bm, with as little overhead (performance penalty) as possible. My first idea would be to try

type
  TBitmapUtils = record
  private
    FBitmap: TBitmap;
  public
    procedure MyProc1;
    procedure MyProc2;
  end;

  TBitmapHelper = class helper for TBitmap
    function Utils: TBitmapUtils; inline;
  end;

where

{ TBitmapUtils }

procedure TBitmapUtils.MyProc1;
begin
  ShowMessageFmt('The width of the bitmap is %d.', [FBitmap.Width]);
end;

procedure TBitmapUtils.MyProc2;
begin
  ShowMessageFmt('The height of the bitmap is %d.', [FBitmap.Height]);
end;

{ TBitmapHelper }

function TBitmapHelper.Utils: TBitmapUtils;
begin
  Result.FBitmap := Self;
end;

Upvotes: 2

Related Questions