Pesquisar

quinta-feira, 5 de março de 2015

Padrões de Desenvolvimento (Design Patterns) - Singleton

E ae pessoal,  tudo certo?

Nesses primeiros posts eu vou escrever um pouco sobre algumas padrões de desenvolvimento (Design Patterns ) que considero importante, a primeira será Singleton.

Na engenharia de software, o padrão de desenvolvimento (Design Pattern) Singleton é um padrão de projeto que restringe a instanciação de uma classe para um objeto. Isso se torna bem útil quando um objeto é necessário para coordenar as ações em todo o sistema.

Quando necessitamos de somente uma instância da classe?

Por exemplo, uma classe de conexão com banco de dados, vamos supor que você terá que chamar diversas vezes a conexão com o banco de dados em um código na mesma execução, se você instanciar toda vez a classe de banco, haverá grande perda de desempenho, assim usando o padrão Singleton, é garantida que nesta execução será instanciada a classe somente uma vez.


Então como saber se uma classe é um Singleton?

Simplesmente obtenha várias vezes a instancia e compare com as anteriores. A classe não é singleton se existir pelo menos uma que não seja igual, a forma de comparar dois objetos a e b tal que a = b é falso.

O padrão singleton necessita que o objeto seja criado pela propria classe, no Delphi não conseguimos suprimir o construtor de TObject (Create), mas existe uma técnica para esconde-lo no auto completar (auto-complete);

Exemplo simples de implementação:
interface

type
  TConexaoComBancoDeDados = class
  strict private
    class var fInstance: TConexaoComBancoDeDados;
    class function GetInstance: TConexaoComBancoDeDados; static;
    constructor Create; virtual; //simplesmente para não aparecer no auto-completar
  public
    class property Instance : TConexaoComBancoDeDados read GetInstance;
  end;

implementation

{ TConexaoComBancoDeDados }

constructor TConexaoComBancoDeDados.Create;
begin
end;

class function TConexaoComBancoDeDados.GetInstance: TConexaoComBancoDeDados;
begin
  if Assigned(fInstance) then
  begin
    fInstance := TConexaoComBancoDeDados.Create;
  end;

  Result := fInstance;
end;


Aqui um teste, pra comprovar o funcionamento:
procedure TForm1.btn1Click(Sender: TObject);
var
  lConexoes01: TConexaoComBancoDeDados;
  lConexoes02: TConexaoComBancoDeDados;
begin
  //..Criando as conexões
  lConexoes01 := TConexaoComBancoDeDados.Instance;

  try

    lConexoes02 := TConexaoComBancoDeDados.Instance;
    try
      // uma compração direta de objetos
      if lConexoes01 = lConexoes02 then
      begin
        ShowMessage('Classe implementa Singleton');
      end else begin
        ShowMessage('Classe NÃO implementa Singleton');
      end;

    finally
      lConexoes02.Free;
    end;
  finally
    lConexoes01.Free;
  end;

end;


Para conseguir perceber a diferença, modifique a método GetInstance da classe TConexaoComBancoDeDados:
class function TConexaoComBancoDeDados.GetInstance: TConexaoComBancoDeDados;
begin
{
  if Assigned(fInstance) then
  begin
    fInstance := TConexaoComBancoDeDados.Create;
  end;

  Result := fInstance;
}
  Result := TConexaoComBancoDeDados.Create;
end;

Há críticas ao uso do padrão Singleton, como alguns consideram que é uma má prática (anti-pattern), julgando que ele usado em demasia, introduz restrições desnecessárias em situações em que uma única instância de uma classe não é realmente necessário, e introduz estado global em um aplicativo. Eu particularmente não concordo.

Resumidamente, mostrei como é feito um Singleton em Delphi, em futuras postagens mostraremos ele sendo usado em "produção"..

Abrass

Nenhum comentário:

Postar um comentário