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.