yanyyx

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

本次修改失败!

为引用空指针的情况下,对象数据无法释放!

还是只能改为,由派生类来创建的方法,加入一个代理中间方法。

============

在构建单例模式下,通过刘艺的《设计模式》里的单例模式,在使用的时候发现问题。

问题描述:

通过使用派生类,分别派生出两个或两个以上的派生,在派生对象实现单例模式下,由于对象管理的引用,是存放于基类的

1 class function TSingleton.GetInstance(Request: Integer): TSingleton;
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;

 

单例的派生类

 

 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;

 

这样,在派生类中,就指定了对象的存放位置,基类,就不能直接生成单例对象了,必须由派生类来生成。

 

完整的代码如下:

 

  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;

 

 

constructor TSingleton.Create;
begin
  
inherited Create;
  
raise Exception.CreateFmt(
    
'Only SingletonInstance Create and Use %s !', [ClassName]);
end;

destructor TSingleton.Destroy;
begin
  
if GetInstance(0nil, False) = Self then GetInstance(2nil, 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(1nil, False);
end;

class procedure TSingleton.ReleaseInstance;
begin
  GetInstance(
0nil, False).Free;
end;

class function TSingleton.SingletonInstance: TSingleton;
begin
 
{ 返回单例类的实例。在创建实例时,该方法取代了 Create 方法 }
 Result :
= GetInstance(1nil, 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;

 

 

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;

 

posted on 2011-08-25 10:21  Yanyyx  阅读(418)  评论(0编辑  收藏  举报