单例模式 改进

本次修改失败!

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

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

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

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

问题描述:

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

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( 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 ;

 

 

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 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/yanyyx/archive/2011/08/25/2152905.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值