Friday, June 12, 2015

Singleton As A Simpleton...

One of the things in object orientation that cannot be gotten around easily is the often repetitive nature of the code you need to write to define objects, their properties and aggregates. Patterns came along relatively recently and addressed this issue by conceptualizing and packaging solutions to many common programming tasks in object orientation.

One such pattern is the Singleton pattern, a one way entry point to instantiate a variable and its memory, ensuring that it is only instanced once in the namespace where the pattern is defined. This ensures that cleanup is simple as well when the namespace containing the instance is freed.

In Delphi, the most common instantiation functions occur when instantiating an object property as in this example:

unit SingletonMyClass;

interface

uses Classes;

type
  TMyClass = class
  private
    FMyList: TList;
    function GetMyList: TList;
  public
    destructor Destroy; override;
    property MyList: TList read GetMyList;
  end;

implementation

function TMyClass.GetMyList: TList;
begin
  { Singleton getter }
  if not Assigned(FMyList) then
    FMyList := TList.Create;
  Result := FMyList;
end;

destructor TMyClass.Destroy;
begin
  FreeAndNil(FMyList);
  inherited;
end;

end.

In the above example, when we instance TMyClass and access the property MyList, the list will only be instanced once. When the TMyClass instance is freed, so will the one instance of the MyList field in TMyClass.

This is a fairly common arrangement in coding and unless you have code generators or an IDE that supports the creation of this common code, it will make up the bulk of your object oriented house keeping.

Of coding and design, efficiency of code can be achieved without compromising the art thereof and efficiency is something that we want if it makes the code more compact, and executes more quickly while getting the required task accomplished predictably.

One of the advantages of object orientation is that if a class exists that does part of the task we need to do or provides a base to build from to do it, we can simply create a descendant class from that class hence not reinventing the wheel. The VCL, Dot Net, and many other object oriented libraries exist for that purpose so lets take a look at how we can use this to reduce the code needed for such housekeeping tasks as handling the Singleton pattern when instancing an object property in a class.

Just for fun, lets call our simplified version the Simpleton:

unit MyLibrary;

interface

uses Classes;

type
  { Simpleton Object creation function }
  function SimpletonObject(AClass: TClass; AObject: TObject): TObject;
  
  { Simpleton Component creation function }
  function SimpletonComponent(AClass: TComponentClass; AComponent: TComponent; AOwner: 

implementation

function SimpletonObject(AClass: TClass; AObject: TObject): TObject;
begin
  if not Assigned(AObject) then
    AObject := AClass.Create;
  Result := AObject;
end;

function SimpletonComponent(AClass: TComponentClass; AComponent: TComponent; AOwner: TComponent): TComponent;
begin
  if not Assigned(AComponent) then
    AComponent := AComponent.Create(AOwner);
  Result := AComponent;

end;

end.


Now before you say: Are you out of your Vulcan mind! lets take a look at the ways this is used in code from the first example:


unit SingletonMyClass;

interface

uses Classes;

type
  TMyClass = class
  private
    FMyList: TList;
    function GetMyList: TList;
  public
    destructor Destroy; override;
    property MyList: TList read GetMyList;
  end;

implementation

function TMyClass.GetMyList: TList;
begin
  FMyList := TList(SimpletonObject(TList,FMyList));
  Result := FList;
end;

destructor TMyClass.Destroy;
begin
  FreeAndNil(FMyList);
  inherited;
end;

end.


Now once again, you might say: Big deal! We dropped one line of code and a comparison. No we didn't. We dropped one line of code everywhere you use a similar Singleton implementation and in compiled code that means several lines of machine code, not to mention the code to load the registers for the function call everywhere you use similar code. This means the code is more compact because the compiler won't just automatically eliminate all code that is redundant.

The only extra thing that we have to take into account is the extra typecast ie:

TList(SimpletonObject(TList,FMyList));

Experience teaches us the ways that we can shorten the distance to our goal.

Sharing those experiences with others can potentially shorten the distance of many to their similar goals.

Another aspect of doing things this way is that for component classes, we don't even need to apply it to a property getter because TComponent derived classes have their own ownership and instance management mechanism, so in a class that doesn't need to share access through a property getter publicly, you can use the Simpleton internally in a method to instance a Field that you might need access to privately. Hence no getter code (though object oriented purists might urge you to consider to limit such use due to the difficulty of finding issues with such code that instances outside of a property getter).

So in example once again:


unit SingletonMyComponent;

interface

uses Classes;

type
  TMyClass = class(TComponent)
  private
    FMyComponent: TComponent;
    procedure DoSomethingPrivate;
  public
    procedure DoSomething;
  end;

implementation

procedure TMyClass.DoSomethingPrivate;
begin
  FMyComponent := TComponent(SimpletonComponent(TComponent,FMyComponent,Self));

  // now do whatever it is we need to do with the FMyComponent instance...
end;

procedure TMyClass.DoSomething;
begin
  DoSomethingPrivate;
end;

end.

In the above example, we don't need property access if the Field is used internally as long as we remember to instance it with the SimpletonComponent function. If it is instanced already, it checks. Then when TMyClass if freed, the memory for FMyComponent is also automatically freed. Reduced code and reduce housekeeping.

Enjoy!

Brian Joseph Johns