PDA

View Full Version : Semi-singleton in Delphi?



cronodragon
13-11-2006, 11:35 PM
Hello :D

As you might know there is a pattern called singleton, which is as class that can be instanced only once in the application. Every new instance of the class, is a reference to the unique object in memory. That mechanism is implemented in the constructor method.

Now, I would like to make a pattern to work with resources, that sometimes is a normal class and sometimes is a singleton. For example, if I have a model with certain filepath, when it is loaded for the first time, a new instance should be created. But when it is loaded again, the constructor should return the reference to the object already in memory.

By the moment I'm using functions to emulate this behavior. But sometimes it's hard to remember when I should use the global function or the constructor to load.

I think this is probably a work with the internals of OOP's mechanisms of Delphi, which I don't know enough. Any idea on how to do this will be greatly appreciated.

grudzio
14-11-2006, 12:09 AM
Look in the library in the Advanced Programming Section. There are two links to tutorials on singleton creation.

cronodragon
14-11-2006, 12:10 AM
Great thanks! :D

cragwolf
14-11-2006, 04:25 AM
Yes, good articles. I prefer this one (http://www.skybound.nl/articles/delphi-singleton/), because any class you inherit from the singleton class will also be a singleton class. That way you can create one apple and one orange, instead of being limited to creating one fruit. :)

cronodragon
14-11-2006, 04:28 AM
Sounds good, I'll check it out too :thumbup:

grudzio
14-11-2006, 06:23 PM
I've found another way of making inheritable singleton. I put constructor in protected section and write separate function to create and return instance of singleton. The instance is declared in the implementation section so it is not visible outside the unit. The constructor is protected so none can call it except derived classes. There is more typing since for each sngleton you have to declare a variable and GetSingleton function.
Here is an example:

unit sing; //first singleton

{$mode objfpc}{$H+}

interface

type

TSingleton = class
private
fData : string;
protected
constructor Create;
public
procedure PrintData; virtual;
end;

function GetSingleton : TSingleton;

implementation

var
asing : TSingleton = nil;

function GetSingleton : TSingleton;
begin
if asing = nil then
asing := TSingleton.Create;
Result := asing;
end;

constructor TSingleton.Create;
begin
inherited;
fData := 'hello world';
end;

procedure TSingleton.PrintData;
begin
Writeln(fData);
end;

end.

unit sing2; //second singleton

{$mode objfpc}{$H+}

interface

uses
sing;

type

TSingleton2 = class(TSingleton)
private
fData2 : string;
protected
constructor Create;
public
procedure PrintData; override;
end;

function GetSingleton2 : TSingleton2;

implementation

var
asing2 : TSingleton2 = nil;

function GetSingleton2 : TSingleton2;
begin
if asing2 = nil then
asing2 := TSingleton2.Create;
Result := asing2;
end;

constructor TSingleton2.Create;
begin
inherited;
fData2 := 'hello world 2';
end;

procedure TSingleton2.PrintData;
begin
inherited;
Writeln(fData2);
end;

end.

program singtest; //test program

{$mode objfpc}{$H+}

uses
sing, sing2;

var
c : char;

begin

GetSingleton.PrintData;
GetSingleton2.PrintData;

ReadLn(c);

GetSingleton.Free;
GetSingleton2.Free;

end.



The if statement can be removed from Get function by moving singleton creation to initialization section of the unit.

I think this solution is closest to C++ implementation based on the static class member.

So, what do you think?

grudzio
14-11-2006, 09:10 PM
My method does not work :( . Even though constructor is in protected section the TSingleton object can be created by calling TSingleton.Create.
It seems that the visibility of the method cannot be changed in derived classes.

cronodragon
14-11-2006, 10:05 PM
The idea is not using a global function, I already do that :P