unit uSingletonDerivado;

interface

uses uSingleton, Dialogs, Classes;

  type
    TMySingletonDerivado = class(TMySingleton)
  private
    class var _MySingletonDerivadoInstance: TObject;
    class var _PreparadoParaLiberarDerivado: Boolean;
  protected
    class procedure PrepararParaLiberar;  override;
    class function GetInstance: TMySingleton; reintroduce; static;
  public

    class function NewInstance: TObject; override;
    procedure FreeInstance; override;

     class property Instance: TMySingleton read GetInstance;
    end;

implementation


{ TMySingletonDerivado }

procedure TMySingletonDerivado.FreeInstance;
begin
  if _PreparadoParaLiberarDerivado then
  begin
    _PreparadoParaLiberarDerivado := False;
    _MySingletonDerivadoInstance := nil;
    inherited;
  end;
end;

class function TMySingletonDerivado.GetInstance: TMySingleton;
begin
  //não usamos TMySingletonDerivado para não dar invalid typecast caso já exista um singleton base criado
  if _MySingletonDerivadoInstance = nil then
    _MySingletonDerivadoInstance := TMySingletonDerivado.Create;

  Result := _MySingletonDerivadoInstance as TMySingleton;
end;

class function TMySingletonDerivado.NewInstance: TObject;
begin
  if (_MySingletonDerivadoInstance = nil) then
  begin
    //_MySingletonDerivadoInstance := inherited NewInstance as TMySingletonDerivado;
    _MySingletonDerivadoInstance := inherited NewInstance;
  end;

  Result := _MySingletonDerivadoInstance;
end;

class procedure TMySingletonDerivado.PrepararParaLiberar;
begin
  _PreparadoParaLiberarDerivado := True;
  inherited;
end;

initialization
  TMySingletonDerivado._MySingletonDerivadoInstance := nil;
  TMySingletonDerivado._PreparadoParaLiberarDerivado := False;



finalization
  if (TMySingletonDerivado._MySingletonDerivadoInstance <> nil) then
  try
    TMySingletonDerivado.PrepararParaLiberar;
    TMySingletonDerivado._MySingletonDerivadoInstance.Free;
  except
    //tratamento de exceção, se precisar
  end;

end.
