单例模式顾名思义就是一个实例,在任何情况下,系统中只能存在某一对象的一个实例。单例模式在应用开发中比较常见,如 Application 或 Logger。

在 Delphi 的以前版本中,实现单例模式比较“另类”,自从 Delphi 后期加入一些新的语法元素后,单例模式的实现显得更为标准,和 C++、Java 中的实现方法几乎一致,最主要原因就是 Delphi 加入了类变量的支持,关键字为”class var”。

Delphi 同时支持类属性,可以让单例的访问更为友好;同时需要注意,在实现单例模式时,一定不要忘记把类本身的 Create 构建函数隐藏,否则的话,单例的实现将没有意义。

下面的代码实现了单例模式的 TLogger:

unit LoggerService;

interface

uses
    SysUtils, Windows, Messages, Classes, Forms, Dialogs;

type
    TLogger = class(TObject)
    private
        class var
        FInstance: TLogger;
        class function GetInstance: TLogger; static;
    protected
        constructor Create;
    public
        procedure Login;
        procedure Logout;
        class procedure ReleaseInstance;
        class property Instance: TLogger read GetInstance;
    end;

implementation

{
************************* TLogger *************************
}

constructor TLogger.Create;
begin
    ShowMessage('Create...');
end;

class function TLogger.GetInstance: TLogger;
begin
    if FInstance = nil then FInstance := TLogger.Create;
    Result := FInstance;
end;

procedure TLogger.Login;
begin
    ShowMessage('Login...');
end;

procedure TLogger.Logout;
begin
    ShowMessage('Logout...');
end;

class procedure TLogger.ReleaseInstance;
begin
    FreeAndNil(FInstance);
end;

end.

通过 TLogger.Instance 属性即可访问日志记录对象的唯一实例,使用 TLogger.ReleaseInstance 释放实例,当然通过 TLogger.Instance.Free 也可释放实例,但在 FInstance 为 Nil 的时候,此种释放方法会先构建一个实例然后再释放,所以 ReleaseInstance 是最佳选择。 Delphi 支持全局变量,如果觉得 TLogger.Instance 这种访问方法显得麻烦,可以定义一个 Logger 全局变量来访问实例,如下:

...
interface
...
var
    Logger: TLogger;
...
implementation
...
initialization
    Logger := TLogger.Instance;

finalization
    TLogger.ReleaseInstance;
    Logger := nil;