zoukankan      html  css  js  c++  java
  • 单例模式 改进

    本次修改失败!

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

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

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

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

    问题描述:

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

    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;
  • 相关阅读:
    python标准库之MultiProcessing库的研究 (1)
    python标准库Beautiful Soup与MongoDb爬喜马拉雅电台的总结
    ASP.NET平台下从浏览器地址栏输入之后发生的事
    async & await 异步编程的一点巧方法
    【MySQL】MySQL一主二从复制环境切换主从库
    【MySQL】MySQL基于二进制文件安装
    【MySQL】MySQL半同步复制
    【MySQL】MySQL搭建主主复制(双主复制/DUAL Master)环境
    【MySQL】MySQL复制
    【MySQL】MySQL搭建主从复制环境
  • 原文地址:https://www.cnblogs.com/yanyyx/p/2152905.html
Copyright © 2011-2022 走看看