T
tseug
Unregistered / Unconfirmed
GUEST, unregistred user!
unit Singleton;
{$B-}
interface
uses
Classes;
type
TSingleton = class(TObject)
protected
class function Lookup(const aClassName: ShortString): Integer;
virtual;
class procedure Register(const aClassName: ShortString;
aInstance: TObject);
virtual;
procedure UnRegister(const aClassName: ShortString);
virtual;
procedure Init;
virtual;
//私有成员初始化
proceduredo
ne;
virtual;
//释放私有成员动态申请的资源
public
class function NewInstance: TObject;
override;
procedure FreeInstance;
override;
end;
implementation
uses
SysUtils;
type
PRegistryItem = ^TRegistryItem;
TRegistryItem = record
ClassName: ShortString;
Instance : TObject;
RefCount : Integer;
end;
var
_Registry : TList;
class function TSingleton.Lookup(const aClassName: ShortString): Integer;
var
Index : Integer;
Item : PRegistryItem;
begin
Result := -1;
Index := 0;
while (Result = -1) and (Index < _Registry.Count)do
begin
Item := _Registry[Index];
if (Item <> nil) and (UpperCase(aClassName) = Item^.ClassName) then
Result := Index;
Inc(Index);
end;
end;
class procedure TSingleton.Register(const aClassName: ShortString;
aInstance: TObject);
var
Item : PRegistryItem;
begin
if Lookup(aClassName) < 0 then
begin
New(Item);
Item^.ClassName := UpperCase(aClassName);
Item^.Instance := aInstance;
Item^.RefCount := 1;
_Registry.Add(Item);
end;
end;
procedure TSingleton.UnRegister(const aClassName: ShortString);
var
Index: Integer;
Item : PRegistryItem;
begin
Index := Lookup(aClassName);
if Index >= 0 then
begin
Item := _Registry[Index];
if Item^.RefCount = 0 then
begin
_Registry.Delete(Index);
Dispose(Item);
end;
end;
end;
class function TSingleton.NewInstance: TObject;
var
Index : Integer;
Item : PRegistryItem;
Instance : TObject;
begin
Index:= Lookup(ClassName);
if Index < 0 then
begin
Instance := inherited NewInstance;
TSingleton(Instance).Init;
Register(ClassName, Instance);
end
else
begin
Item := _Registry[Index];
Instance := Item^.Instance;
Inc(Item^.RefCount);
end;
Result := Instance;
end;
procedure TSingleton.FreeInstance;
var
Index : Integer;
Item : PRegistryItem;
FreeIt : Boolean;
begin
FreeIt := True;
Index:= Lookup(ClassName);
if Index >= 0 then
begin
Item := _Registry[Index];
Dec(Item^.RefCount);
if Item^.RefCount > 0 then
FreeIt := False;
end;
if FreeIt then
begin
UnRegister(ClassName);
do
ne;
inherited FreeInstance;
end;
end;
procedure TSingleton.Init;
begin
end;
procedure TSingleton.Done;
begin
end;
//-------
procedure Free_Registry;
var
Index : Integer;
Item : PRegistryItem;
begin
if Assigned(_Registry) then
begin
for Index := 0 to _Registry.Count - 1do
begin
Item := _Registry[Index];
if Item <> nil then
Dispose(Item);
end;
_Registry.Free;
_Registry := nil;
end;
end;
initialization
_Registry := TList.Create;
finalization
Free_Registry;
end.
{$B-}
interface
uses
Classes;
type
TSingleton = class(TObject)
protected
class function Lookup(const aClassName: ShortString): Integer;
virtual;
class procedure Register(const aClassName: ShortString;
aInstance: TObject);
virtual;
procedure UnRegister(const aClassName: ShortString);
virtual;
procedure Init;
virtual;
//私有成员初始化
proceduredo
ne;
virtual;
//释放私有成员动态申请的资源
public
class function NewInstance: TObject;
override;
procedure FreeInstance;
override;
end;
implementation
uses
SysUtils;
type
PRegistryItem = ^TRegistryItem;
TRegistryItem = record
ClassName: ShortString;
Instance : TObject;
RefCount : Integer;
end;
var
_Registry : TList;
class function TSingleton.Lookup(const aClassName: ShortString): Integer;
var
Index : Integer;
Item : PRegistryItem;
begin
Result := -1;
Index := 0;
while (Result = -1) and (Index < _Registry.Count)do
begin
Item := _Registry[Index];
if (Item <> nil) and (UpperCase(aClassName) = Item^.ClassName) then
Result := Index;
Inc(Index);
end;
end;
class procedure TSingleton.Register(const aClassName: ShortString;
aInstance: TObject);
var
Item : PRegistryItem;
begin
if Lookup(aClassName) < 0 then
begin
New(Item);
Item^.ClassName := UpperCase(aClassName);
Item^.Instance := aInstance;
Item^.RefCount := 1;
_Registry.Add(Item);
end;
end;
procedure TSingleton.UnRegister(const aClassName: ShortString);
var
Index: Integer;
Item : PRegistryItem;
begin
Index := Lookup(aClassName);
if Index >= 0 then
begin
Item := _Registry[Index];
if Item^.RefCount = 0 then
begin
_Registry.Delete(Index);
Dispose(Item);
end;
end;
end;
class function TSingleton.NewInstance: TObject;
var
Index : Integer;
Item : PRegistryItem;
Instance : TObject;
begin
Index:= Lookup(ClassName);
if Index < 0 then
begin
Instance := inherited NewInstance;
TSingleton(Instance).Init;
Register(ClassName, Instance);
end
else
begin
Item := _Registry[Index];
Instance := Item^.Instance;
Inc(Item^.RefCount);
end;
Result := Instance;
end;
procedure TSingleton.FreeInstance;
var
Index : Integer;
Item : PRegistryItem;
FreeIt : Boolean;
begin
FreeIt := True;
Index:= Lookup(ClassName);
if Index >= 0 then
begin
Item := _Registry[Index];
Dec(Item^.RefCount);
if Item^.RefCount > 0 then
FreeIt := False;
end;
if FreeIt then
begin
UnRegister(ClassName);
do
ne;
inherited FreeInstance;
end;
end;
procedure TSingleton.Init;
begin
end;
procedure TSingleton.Done;
begin
end;
//-------
procedure Free_Registry;
var
Index : Integer;
Item : PRegistryItem;
begin
if Assigned(_Registry) then
begin
for Index := 0 to _Registry.Count - 1do
begin
Item := _Registry[Index];
if Item <> nil then
Dispose(Item);
end;
_Registry.Free;
_Registry := nil;
end;
end;
initialization
_Registry := TList.Create;
finalization
Free_Registry;
end.