您的位置:首页 > 编程语言 > Delphi

设计模式学习笔记5:Singleton模式及其Delphi实现

2005-12-06 16:51 1116 查看
Singleton(单件)模式是一种很有用的设计模式。它的意图的是:仅仅创建一个类的实例,并提供一个访问它的全局访问点。全局变量使的一个对象易被访问,但不能防止你实例化多个对象。单件模式的目的就是确保在程序的生命周期内只有一个实例存在。
多实例实现了数据的并行访问,而单例模式是把它变成串行访问。所以这模式的用途非常的广泛,如处理数据库连接的访问等等。
Delphi实现Singleton也有许多方案,在此列出三种。
方案一:Java或者C++中,类中的变量可以修饰为Static表示该变量不依赖于类的实例而单独存在,在Delphi中没有类似的关键字,所以可以定义一个单元的私有变量来实现对类实例的引用计数。以下代码就是用的此种方案:
unit Unit2;
interface
type
  TSingleton = class
  public
    class function NewInstance: TObject; override;
    procedure FreeInstance; override;
    class function RefCount: Integer;
  end;
implementation
var
  Instance  : TSingleton  = nil;
  Ref_Count : Integer     = 0;
procedure TSingleton.FreeInstance;
begin
  Dec( Ref_Count );
  if ( Ref_Count = 0 ) then
  begin
    Instance := nil;
    // Destroy private variables here
    inherited FreeInstance;
  end;
end;
class function TSingleton.NewInstance: TObject;
begin
  if ( not Assigned( Instance ) ) then
  begin
    Instance := TSingleton(inherited NewInstance);
    // Initialize private variables here, like this:
    //   TSingleton(Result).Variable := Value;
  end;
  Result := Instance;
  Inc(Ref_Count);
end;
class function TSingleton.RefCount: Integer;
begin
  Result := Ref_Count;
end;
Instance需要声明在Implementation部分,而不要声明在单元Interface部分,这样变量对单元外的用户是不可见的,这样可以保护变量不会被用户误修改。
可以用下面的代码看到测试的效果,你可加上Pointer将它们的地址打印出来,就更加直观了!
procedure TForm1.Button1Click(Sender: TObject);
var
  sing1, sing2: TSingleton;
  obj1, obj2: TObject;
begin
  sing1:=TSingleton.Create;
  sing1.Create;
  showmessage(IntToStr(sing1.RefCount));
  sing2:=TSingleton.Create;
  sing2.Create;
  showmessage(IntToStr(sing2.RefCount));
  if sing1=sing2 then
    showmessage('同地址!');
  else
    showmessage('不同地址!');
  sing1.Free;
  sing2.Free;
  //
  obj1:=TObject.Create;
  obj2:=TObject.Create;
  if obj1=obj2 then
    showmessage('同地址!')
  else
    showmessage('不同地址!');
  obj1.Free;
  obj2.Free;
end;
这种方法是根据Delphi的对象机制作的处理。可以像多例类一样使用Create和Free方法来使用它!但是这种方法有一个缺点,就是这种Singleton类不能有多个子类!因为它只会创建一个。
参考: Creating a real singleton class in Delphi 5 by Lasse

方案二:此种方法是White Ants提供的,代码如下:
unit Singleton2;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;
type
  TSingleton2 = class (TObject)
  private
  protected
    constructor CreateInstance;
    class function AccessInstance(Request: Integer): TSingleton2;
    procedure SetTestValue(Value: Integer);
  public
    constructor Create;
    destructor Destroy; override;
    class function Instance: TSingleton2;
    class procedure ReleaseInstance;
  end;
 
implementation
{$J+}
{
********************************** TSingleton2 **********************************
}
constructor TSingleton2.Create;
begin
  inherited Create;
  raise Exception.CreateFmt('只能通过Instance方法来创建和访问%s的实例!',
      [ClassName]);
end;
constructor TSingleton2.CreateInstance;
begin
  inherited Create;
end;
destructor TSingleton2.Destroy;
begin
  if AccessInstance(0) = Self then AccessInstance(2);
  inherited Destroy;
end;
class function TSingleton2.AccessInstance(Request: Integer): TSingleton2; 
  const
    FInstance: TSingleton2 = nil; 
begin
  {
  AccessInstance(0):不作任何处理,供释放实例对象时使用。
  AccessInstance(1):存在该实例时直接使用,不存在时则创建该实例。
  AccessInstance(2):返回一个空指针,用于重新设置实例。
  }
  case Request of
    0 : ;
    1 : if not Assigned(FInstance) then
        begin
          FInstance := CreateInstance;
          FInstance.FConnected:=false;
        end;
    2 : FInstance := nil;
  else
    raise Exception.CreateFmt(' %d 是AccessInstance()中的非法调用参数。',
        [Request]);
  end;
  Result := FInstance;
end;
class function TSingleton2.Instance: TSingleton2;
begin
  //返回实例
  Result := AccessInstance(1);
end;
class procedure TSingleton2.ReleaseInstance;
begin
  AccessInstance(0).Free;
end;
end.
这种方案最关键的地方在于类方法AccessInstance中有一个Singleton常量!
参考:Thinking in patterns with Delphi by Liuyi
方案三:这是Delphi2006中生成的Singleton版本,由于对Delphi语言的增强,实现Singleton变得和Java与C++一样的简单!还是看看代码:
  TSingleton = class
  strict private
    constructor Create;
  class var
    FInstance:TSingleton;
  public
    class function GetInstance: TSingleton;
    procedure FreeInstance;
  end; 
implementation
constructor TSingleton.Create;
begin
  inherited;
end;
class function TSingleton.GetInstance: TSingleton;
begin
  If FInstance = nil Then
  begin
    FInstance := TSingleton.Create();
  end;
  Result := FInstance;
end;
procedure TSingleton.FreeInstance;
begin
  FInstance:=nil;
end;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息