Title: How to implement a singleton
Question:
Answer:
Some design patterns are:
Singleton:
"Ensure a class has only one instance, and provide a global point of
access to it."
Adapter:
"Convert the interface of a class into another interface clients
expect. Adapter lets classes work together that couldn't otherwise
because of incompatible interfaces."
Template Method:
"Define the skeleton of an algorithm in an operation, deferring
some steps to subclasses. Template Method lets subclasses
redefine certain steps of an algorithm without changing the
algorithm's structure."
Builder:
"Separate the construction of a complex object from its representation
so that the same construction process can create different
representations."
Abstract Factory:
"Provide an interface for creating families of related or dependant
objects without specifying their concrete classes."
Factory Method:
"Define an interface for creating an object, but let subclasses
decide which class to instantiate. Factory method lets a class
defer instantiation to subclasses."
At http://www.obsof.com/pattern.html#Intro you find Delphi examples
for these patterns. One of this examples shows how to implement a singleton.
To implement a class of this type, override the constructor and destructor of
the class to refer to a global (interface) variable of the class.
Abort the constructor if the variable is assigned, otherwise create the
instance and assign the variable.
In the destructor, clear the variable if it refers to the instance being
destroyed.
Note: To make the creation and destruction of the single instance automatic,
include its creation in the initialization section of the unit. To destroy
the instance, include its destruction in an ExitProc (Delphi 1) or in the
finalization section of the unit (Delphi 2).
The following Delphi 1 example illustrates two singleton classes, one derived
from TComponent and another derived from TObject.
unit Singletn;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs;
type
TCSingleton = class(TComponent)
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
TOSingleton = class(TObject)
public
constructor Create;
destructor Destroy; override;
end;
var
Global_CSingleton: TCSingleton;
Global_OSingleton: TOSingleton;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Design Patterns', [TCSingleton]);
end;
{ TCSingleton }
constructor TCSingleton.Create(AOwner: TComponent);
begin
if Global_CSingleton nil then
{NB could show a message or raise a different exception here}
Abort
else begin
inherited Create(AOwner);
Global_CSingleton := Self;
end;
end;
destructor TCSingleton.Destroy;
begin
if Global_CSingleton = Self then
Global_CSingleton := nil;
inherited Destroy;
end;
{ TOSingleton }
constructor TOSingleton.Create;
begin
if Global_OSingleton nil then
{NB could show a message or raise a different exception here}
Abort
else
Global_OSingleton := Self;
end;
destructor TOSingleton.Destroy;
begin
if Global_OSingleton = Self then
Global_OSingleton := nil;
inherited Destroy;
end;
procedure FreeGlobalObjects; far;
begin
if Global_CSingleton nil then
Global_CSingleton.Free;
if Global_OSingleton nil then
Global_OSingleton.Free;
end;
begin
AddExitProc(FreeGlobalObjects);
end.