Introdução ao Design Pattern Singleton com Delphi
Veja nesta Quick um exemplo prático de Singleton em Delphi.
Olá galera, nesta Quick Tips irei mostrar um dos padrões de projetos mais utilizados hoje em dia no desenvolvimento de Software: o padrão Singleton.
Com o Singleton podemos ter a certeza de que só existirá um único objeto instanciado para determinada classe. Um exemplo seria o usuário conectado ao sistema ou até mesmo a conexão direta ao banco de dados.
Vou criar uma unit e seu nome será uUsuario. Nela implementaremos uma série de configurações dentro de uma classe chamada TUsuario.
Ao criar uma unit vamos declarar a mesma da seguinte forma, e salvar como uUsuario:
unit uUsuario;
interface
uses
uDM, DB, SqlExpr, SysUtils, Dialogs, IdHashMessageDigest;
type
TUsuario = class
Private
{ Objetivo : Podemos notar que existem fields/variáveis Class Var, estes
são necessários que configuremos desta forma, para podermos armazenar o
conteúdo do usuário ao ser localizado na base de dados, quando usamos um
método de Class, para acessarmos Fields dentro dele, só podemos acessar
quando estes são de Class também }
class var FID: Integer;
class var FSenha: String;
class var FNivel: Integer;
class var FUsuario: String;
class var FInstance: TUsuario;
constructor CreatePrivate;
constructor Create;
{ private declarations }
protected
{ protected declarations }
public
{ public declarations }
{ Objetivo : Efetuar o login a uma base de dados passando usuário e senha,
além da conexão ao qual se deseja conectar }
class function Login(AUsuario, ASenha: String;xConexao: TSQLConnection):
Boolean;
{ Objetivo : alterar a senha de um usuário logado por exemplo }
class function ChangePassword(strOldPassword, trNewPassword,strCheckPassword:
String; xConexao : TSQLConnection):Boolean;
{ Objetivo : Obter a instancia caso exista, ou criar a mesma, apenas uma única vez }
class function GetInstance: TUsuario;
{ Objetivo : Função criada em outro artigo, serve para podermos criptografar uma
string utilizando Hash MD5, observe que demos uses em IdHashMessageDigest }
class function Criptografar(const Value: string): string; static;
{ Objetivo : Função para retornar o nome do usuário logado }
class function GetUsuarioLogado: String;
{ Objetivo : Propriedades de configuração da minha tabela de usuário, configure e
altere de acordo com a sua necessidade }
class property ID: Integer read FID;
class property Usuario: String read FUsuario;
class property Senha: String read FSenha;
class property Nivel: Integer read FNivel;
end;
Agora iremos mostrar a implementação dos métodos declarados:
class function TUsuario.Criptografar(const Value: string): string;
var
xMD5: TIdHashMessageDigest5;
begin
xMD5 := TIdHashMessageDigest5.Create;
try
Result := xMD5.HashStringAsHex(Value);
finally
xMD5.Free;
end;
end;
class function TUsuario.ChangePassword(strOldPassword,
strNewPassword, strCheckPassword: String; xConexao : TSQLConnection): Boolean;
var
xQry : TSQLQuery;
begin
xQry := TSQLQuery.Create(Nil);
xQry.SQLConnection := xConexao;
if FSenha = Criptografar(strOldPassword) then
begin
if strNewPassword = strCheckPassword then
begin
try
xQry.SQL.Add('UPDATE USUARIO SET SENHA =
'+QuotedStr(Criptografar(strNewPassword))+
' WHERE IDUSUARIO = '+ IntToStr(FID));
xQry.ExecSQL;
Result := True;
FSenha := Criptografar(strNewPassword);
MessageDlg('Senha alterada com sucesso !!!!',
mtInformation,[mbOK],0);
finally
FreeAndNil(xQry);
end;
end
else
MessageDlg('As senhas não conferem !!!!',
mtInformation,[mbOK],0);
end
else
MessageDlg('A senha antiga não confere !!!!',
mtInformation,[mbOK],0);
end;
constructor TUsuario.Create;
begin
raise Exception.Create('Para obter uma instância de TUsuario utilize
TUsuario.GetInstance !');
end;
constructor TUsuario.CreatePrivate;
begin
inherited Create;
end;
class function TUsuario.GetInstance: TUsuario;
begin
if not Assigned(FInstance) then
FInstance := TUsuario.CreatePrivate;
Result := FInstance;
end;
class function TUsuario.GetUsuarioLogado: String;
begin
Result := FUsuario;
end;
class function TUsuario.Login(AUsuario, ASenha: String; xConexao:
TSQLConnection): Boolean;
var
xQry : TSQLQuery;
begin
try
xry := TSQLQuery.Create(Nil);
xQry.SQLConnection := xConexao;
xQry.SQL.Add('SELECT * FROM USUARIO WHERE DESCRICAO =
'+QuotedStr(AUsuario)+
' AND SENHA = '+QuotedStr(Criptografar(ASenha)));
xQry.Open;
if not xQry.IsEmpty then
begin
FID := xQry.Fields[0].AsInteger;
FUsuario := xQry.Fields[1].AsString;
FSenha := xQry.Fields[2].AsString;
FNivel := xQry.Fields[3].AsInteger;
Result := True;
end
else
ShowMessage('Usuario ou senha inválidos');
except
on E : EXCEPTION do
raise Exception.Create('ERRO NAO ESPERADO '+
E.Message +#13+
E.ClassName + ' - - - ' + E.UnitName);
end;
end;
end.
O que é interessante nestes métodos, é que podemos aproveitá-los para outros projetos, montados nesta uUsuario.pas.
Agora irei mostrar como usar os métodos implementados anteriormente na unit uUsuario.pas. Veja como é simples a implementação da mesma.
- Login: monte uma tela basicamente com dois Edits(EdtUsuario,EdtSenha) e dois BitBtn(BtnAcessar,BtnSenha), além de uma Progressbar (apenas de enfeite).
procedure TFrmLogin.BtnAcessarClick(Sender: TObject); var I: Integer; begin BtnAcessar.Enabled := False; { Obs: Veja que estou passando uma Conexão, esta é do tipo TSQLConnection} if TUsuario.GetInstance.Login(EdtUsuario.Text, EdtSenha.Text, DM.Conexao ) then begin ProgressBar1.Max := 100; for I := 0 to 100 - 1 do begin ProgressBar1.Position := I; Sleep(5); Application.ProcessMessages; end; Close; ModalResult := MrOk; end; BtnAcessar.Enabled := True; end;
- GetUsuarioLogado: este é bem simples, onde uma function resulta uma string. Podemos colocar, por exemplo, em uma StatusBar.
procedure TFrmLogin.BtnAcessarClick(Sender: TObject); begin StatusBar1.Panels[0].Text := TUsuario.GetUsuarioLogado; { Obs: Como os métodos são de Classe, podemos pegar os mesmos também da seguinte forma} StatusBar1.Panels[1].Text := TUsuario.Usuario; StatusBar1.Panels[2].Text := TUsuario.Nivel; end;
- ChangePassword: monte uma tela basicamente com quatro Edits(EdtUsuario,EdtSenha, EdtNovaSenha, EdtConfirmaSenha), dois BitBtn(BtnMudar,BtnSenha) uma dica de layout.
procedure TFrmMudarSenha.btnMudarClick(Sender: TObject); begin TUsuario.GetInstance.ChangePassword(EdtSenha.Text, EdtNovaSenha.Text, EdtConfirmaSenha.Text, DM.Conexao); Close; end; procedure TFrmMudarSenha.FormShow(Sender: TObject); begin { Obs: Fiz com que ao abrir a tela para mudar a senha, o usuário já seja carregado no EdtUsuario} EdtUsuario.Text := TUsuario.GetUsuarioLogado; end;
Fico por aqui ate à próxima Quick Tips.
Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Artigo