本次修改失败!
为引用空指针的情况下,对象数据无法释放!
还是只能改为,由派生类来创建的方法,加入一个代理中间方法。
============
在构建单例模式下,通过刘艺的《设计模式》里的单例模式,在使用的时候发现问题。
问题描述:
通过使用派生类,分别派生出两个或两个以上的派生,在派生对象实现单例模式下,由于对象管理的引用,是存放于基类的
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;