本次修改失败!
为引用空指针的情况下,对象数据无法释放!
还是只能改为,由派生类来创建的方法,加入一个代理中间方法。
============
在构建单例模式下,通过刘艺的《设计模式》里的单例模式,在使用的时候发现问题。
问题描述:
通过使用派生类,分别派生出两个或两个以上的派生,在派生对象实现单例模式下,由于对象管理的引用,是存放于基类的
1
class
function
TSingleton.GetInstance(Request: Integer
): TSingleton;
2 const
3 FInstance: TSingleton = nil ;
2 const
3 FInstance: TSingleton = nil ;
中,如果,在派生类直接使用这个过程,那么,所有的派生类将使用同一个对象引用,这样,程序就报错了。达不到了,目的。
现将代码更改如下
单例基类
1
{
将基类里的常量由派生类的常量来替代
}
2 class function TSingleton.GetInstance(Request: Integer; FInstance : TSingleton;
3 AskSelf : Boolean): TSingleton;
4 begin
5 {
6 Request = 0 : 不作任何处理,供释放实例对象时使用
7 Request = 1 : 存在该实例时直接使用,不存在时刚创建该实例
8 Request = 2 : 返回一个指针,用于重新设置实例
9 }
10 case Request of
11 0 : ;
12 1 : if not Assigned(FInstance) then
13 begin
14 FInstance : = CreateInstance;
15 end ;
16 2 : FInstance : = nil ;
17 else
18 raise Exception.CreateFmt(
19 ' %d is GetInstance() bad parameter ' , [Request]);
20 end ;
21 Result : = FInstance;
22
23 end ;
2 class function TSingleton.GetInstance(Request: Integer; FInstance : TSingleton;
3 AskSelf : Boolean): TSingleton;
4 begin
5 {
6 Request = 0 : 不作任何处理,供释放实例对象时使用
7 Request = 1 : 存在该实例时直接使用,不存在时刚创建该实例
8 Request = 2 : 返回一个指针,用于重新设置实例
9 }
10 case Request of
11 0 : ;
12 1 : if not Assigned(FInstance) then
13 begin
14 FInstance : = CreateInstance;
15 end ;
16 2 : FInstance : = nil ;
17 else
18 raise Exception.CreateFmt(
19 ' %d is GetInstance() bad parameter ' , [Request]);
20 end ;
21 Result : = FInstance;
22
23 end ;
单例的派生类
1
class
function
TSysError.GetInstance(Request: Integer; FInstance : TSingleton;
2 AskSelf : Boolean): TSysError;
3 { AskSelf 判断传入的单例对象是否存在,
4 当AskSelf 为 True ,调用这个过程的是这个类
5 为 False ,调用这个过程的是派生类 }
6 const
7 { $J+ }
8 SelfObj: TSysError = nil ;
9 { $J- }
10 begin
11 if AskSelf then
12 Result : = TSysError( inherited GetInstance(Request, SelfObj, False))
13 else
14 Result : = TSysError( inherited GetInstance(Request, FInstance, False));
15 end ;
2 AskSelf : Boolean): TSysError;
3 { AskSelf 判断传入的单例对象是否存在,
4 当AskSelf 为 True ,调用这个过程的是这个类
5 为 False ,调用这个过程的是派生类 }
6 const
7 { $J+ }
8 SelfObj: TSysError = nil ;
9 { $J- }
10 begin
11 if AskSelf then
12 Result : = TSysError( inherited GetInstance(Request, SelfObj, False))
13 else
14 Result : = TSysError( inherited GetInstance(Request, FInstance, False));
15 end ;
这样,在派生类中,就指定了对象的存放位置,基类,就不能直接生成单例对象了,必须由派生类来生成。
完整的代码如下:
TSingleton
=
class
(TObject)
private
FSingletonProperty: Integer;
procedure SetSingletonProperty(Value: Integer);
protected
constructor CreateInstance; virtual ;
class function GetInstance(Request: Integer; FInstance : TSingleton;
AskSelf : Boolean): TSingleton;
procedure FreeData; virtual ;
procedure InitData; virtual ;
public
constructor Create;
destructor Destroy; override ;
class function Instance: TSingleton;
class procedure ReleaseInstance;
class function SingletonInstance: TSingleton;
procedure SingletonOperation;
property SingletonProperty: Integer read FSingletonProperty
write SetSingletonProperty;
end ;
private
FSingletonProperty: Integer;
procedure SetSingletonProperty(Value: Integer);
protected
constructor CreateInstance; virtual ;
class function GetInstance(Request: Integer; FInstance : TSingleton;
AskSelf : Boolean): TSingleton;
procedure FreeData; virtual ;
procedure InitData; virtual ;
public
constructor Create;
destructor Destroy; override ;
class function Instance: TSingleton;
class procedure ReleaseInstance;
class function SingletonInstance: TSingleton;
procedure SingletonOperation;
property SingletonProperty: Integer read FSingletonProperty
write SetSingletonProperty;
end ;
constructor
TSingleton.Create;
begin
inherited Create;
raise Exception.CreateFmt(
' Only SingletonInstance Create and Use %s ! ' , [ClassName]);
end ;
destructor TSingleton.Destroy;
begin
if GetInstance( 0 , nil , False) = Self then GetInstance( 2 , nil , False);
FreeData;
inherited Destroy;
end ;
constructor TSingleton.CreateInstance;
begin
inherited Create;
InitData;
end ;
procedure TSingleton.FreeData;
begin
end ;
{ 将基类里的常量由派生类的常量来替代 }
class function TSingleton.GetInstance(Request: Integer; FInstance : TSingleton;
AskSelf : Boolean): TSingleton;
// const
// FInstance: TSingleton = nil ;
begin
{
Request = 0 : 不作任何处理,供释放实例对象时使用
Request = 1 : 存在该实例时直接使用,不存在时刚创建该实例
Request = 2 : 返回一个指针,用于重新设置实例
}
case Request of
0 : ;
1 : if not Assigned(FInstance) then
begin
FInstance : = CreateInstance;
end ;
2 : FInstance : = nil ;
else
raise Exception.CreateFmt(
' %d is GetInstance() bad parameter ' , [Request]);
end ;
Result : = FInstance;
end ;
procedure TSingleton.InitData;
begin
end ;
class function TSingleton.Instance: TSingleton;
begin
// 返回实例
Result : = GetInstance( 1 , nil , False);
end ;
class procedure TSingleton.ReleaseInstance;
begin
GetInstance( 0 , nil , False).Free;
end ;
class function TSingleton.SingletonInstance: TSingleton;
begin
{ 返回单例类的实例。在创建实例时,该方法取代了 Create 方法 }
Result : = GetInstance( 1 , nil , False);
end ;
procedure TSingleton.SingletonOperation;
begin
{ 完成某一特定的操作 }
end ;
procedure TSingleton.SetSingletonProperty(Value: Integer);
begin
{ 设置某一特定的属性 }
end ;
begin
inherited Create;
raise Exception.CreateFmt(
' Only SingletonInstance Create and Use %s ! ' , [ClassName]);
end ;
destructor TSingleton.Destroy;
begin
if GetInstance( 0 , nil , False) = Self then GetInstance( 2 , nil , False);
FreeData;
inherited Destroy;
end ;
constructor TSingleton.CreateInstance;
begin
inherited Create;
InitData;
end ;
procedure TSingleton.FreeData;
begin
end ;
{ 将基类里的常量由派生类的常量来替代 }
class function TSingleton.GetInstance(Request: Integer; FInstance : TSingleton;
AskSelf : Boolean): TSingleton;
// const
// FInstance: TSingleton = nil ;
begin
{
Request = 0 : 不作任何处理,供释放实例对象时使用
Request = 1 : 存在该实例时直接使用,不存在时刚创建该实例
Request = 2 : 返回一个指针,用于重新设置实例
}
case Request of
0 : ;
1 : if not Assigned(FInstance) then
begin
FInstance : = CreateInstance;
end ;
2 : FInstance : = nil ;
else
raise Exception.CreateFmt(
' %d is GetInstance() bad parameter ' , [Request]);
end ;
Result : = FInstance;
end ;
procedure TSingleton.InitData;
begin
end ;
class function TSingleton.Instance: TSingleton;
begin
// 返回实例
Result : = GetInstance( 1 , nil , False);
end ;
class procedure TSingleton.ReleaseInstance;
begin
GetInstance( 0 , nil , False).Free;
end ;
class function TSingleton.SingletonInstance: TSingleton;
begin
{ 返回单例类的实例。在创建实例时,该方法取代了 Create 方法 }
Result : = GetInstance( 1 , nil , False);
end ;
procedure TSingleton.SingletonOperation;
begin
{ 完成某一特定的操作 }
end ;
procedure TSingleton.SetSingletonProperty(Value: Integer);
begin
{ 设置某一特定的属性 }
end ;
派生类:
TSysError
=
class
(TSingleton)
private
FErrorList : TList;
protected
constructor CreateInstance; override ;
class function GetInstance(Request: Integer; FInstance : TSingleton;
AskSelf : Boolean): TSysError;
procedure FreeData; override ;
procedure InitData; override ;
public
procedure AddErrorList(Style : Integer; aNode : Pointer);
procedure ClearErrorList;
class function Instance: TSysError;
property ErrorList : TList read FErrorList;
end ;
private
FErrorList : TList;
protected
constructor CreateInstance; override ;
class function GetInstance(Request: Integer; FInstance : TSingleton;
AskSelf : Boolean): TSysError;
procedure FreeData; override ;
procedure InitData; override ;
public
procedure AddErrorList(Style : Integer; aNode : Pointer);
procedure ClearErrorList;
class function Instance: TSysError;
property ErrorList : TList read FErrorList;
end ;
procedure
TSysError.AddErrorList(Style : Integer; aNode : Pointer);
var
ErrNode : PErrNode;
begin
New(ErrNode);
ErrNode.Style : = Style;
ErrNode.ErrNode : = aNode;
FErrorList.Add(ErrNode);
end ;
constructor TSysError.CreateInstance;
begin
inherited CreateInstance;
end ;
procedure TSysError.ClearErrorList;
var
i : integer;
begin
for i : = 0 to FErrorList.Count - 1 do
begin
Dispose(PErrNode(FErrorList.List^[i]).ErrNode);
Dispose(FErrorList.List^[i]);
end ;
FErrorList.Clear;
end ;
procedure TSysError.FreeData;
begin
ClearErrorList;
FErrorList.Free;
end ;
class function TSysError.GetInstance(Request: Integer; FInstance : TSingleton;
AskSelf : Boolean): TSysError;
{ AskSelf 判断传入的单例对象是否存在,
当AskSelf 为 True ,调用这个过程的是这个类
为 False ,调用这个过程的是派生类 }
const
{ $J+ }
SelfObj: TSysError = nil ;
{ $J- }
begin
if AskSelf then
Result : = TSysError( inherited GetInstance(Request, SelfObj, False))
else
Result : = TSysError( inherited GetInstance(Request, FInstance, False));
end ;
procedure TSysError.InitData;
begin
FErrorList : = TList.Create;
end ;
class function TSysError.Instance: TSysError;
begin
Result : = TSysError( inherited Instance);
end ;
var
ErrNode : PErrNode;
begin
New(ErrNode);
ErrNode.Style : = Style;
ErrNode.ErrNode : = aNode;
FErrorList.Add(ErrNode);
end ;
constructor TSysError.CreateInstance;
begin
inherited CreateInstance;
end ;
procedure TSysError.ClearErrorList;
var
i : integer;
begin
for i : = 0 to FErrorList.Count - 1 do
begin
Dispose(PErrNode(FErrorList.List^[i]).ErrNode);
Dispose(FErrorList.List^[i]);
end ;
FErrorList.Clear;
end ;
procedure TSysError.FreeData;
begin
ClearErrorList;
FErrorList.Free;
end ;
class function TSysError.GetInstance(Request: Integer; FInstance : TSingleton;
AskSelf : Boolean): TSysError;
{ AskSelf 判断传入的单例对象是否存在,
当AskSelf 为 True ,调用这个过程的是这个类
为 False ,调用这个过程的是派生类 }
const
{ $J+ }
SelfObj: TSysError = nil ;
{ $J- }
begin
if AskSelf then
Result : = TSysError( inherited GetInstance(Request, SelfObj, False))
else
Result : = TSysError( inherited GetInstance(Request, FInstance, False));
end ;
procedure TSysError.InitData;
begin
FErrorList : = TList.Create;
end ;
class function TSysError.Instance: TSysError;
begin
Result : = TSysError( inherited Instance);
end ;