Muitos componentes, no entanto, vão se tornando obsoletos conforme evoluem os sistemas operacionais, as técnicas de programação e mesmo o hardware. A ABC71, por exemplo, passou bastante tempo usando BDE em suas aplicações para acessar banco de dados. Quando a Borland (hoje Embarcadero) descontinuou a evolução dessa biblioteca, tivemos que adotar outra solução para acesso aos dados.
O Design Pattern estrutural Adapter, às vezes também chamado de Wrapper, fornece uma solução bastante prática para esse tipo de problema, de modo que foi preciso alterar basicamente apenas um arquivo fonte para por nosso ERP Omega para funcionar com ADO no lugar do BDE. Veja abaixo o diagrama UML para a solução típica do Adapter.A solução típica é composta de 4 classes, sendo que a nomenclatura delas é a seguinte:
O Target é a classe que define a interface que o programa vai enxergar, isso é, quais são os nomes de métodos e propriedades que estarão disponíveis para o programa, independente de qual tecnologia será realmente utilizada. No diagrama anterior, a classe TWDBManager exerce esse papel.
O Adapter faz o meio de campo, isto é, implementa os métodos descritos pelo Target usando métodos e propriedades expostos pela classe que está sendo encapsulada (o Adaptee). No diagrama acima, esse papel cabe às classes TWBDEMan e TWADOMan, que adaptam o acesso respectivamente às funções do BDE e do ADO.
O Adaptee corresponde à classe que efetivamente realiza as tarefas que precisamos. Ela pode vir tanto de uma tecnologia específica dentro do mesmo ambiente de desenvolvimento (como é o caso do ADO e do BDE) quanto vir de uma biblioteca ou componente de terceiros.
A classe Client faz uso dos métodos expostos pelo Target para realizar as operações de que precisa. Ela não tem conhecimento de qual tecnologia ou biblioteca ou componente está sendo de fato usado. No exemplo, esse é o papel exercido pelo TWBusinessObj.
O Adapter faz o meio de campo, isto é, implementa os métodos descritos pelo Target usando métodos e propriedades expostos pela classe que está sendo encapsulada (o Adaptee). No diagrama acima, esse papel cabe às classes TWBDEMan e TWADOMan, que adaptam o acesso respectivamente às funções do BDE e do ADO.
O Adaptee corresponde à classe que efetivamente realiza as tarefas que precisamos. Ela pode vir tanto de uma tecnologia específica dentro do mesmo ambiente de desenvolvimento (como é o caso do ADO e do BDE) quanto vir de uma biblioteca ou componente de terceiros.
A classe Client faz uso dos métodos expostos pelo Target para realizar as operações de que precisa. Ela não tem conhecimento de qual tecnologia ou biblioteca ou componente está sendo de fato usado. No exemplo, esse é o papel exercido pelo TWBusinessObj.
Qual das classes que implementam a interface do Target deve ser instanciada é uma decisão que pode ser resolvida pelo Pattern Factory Method, já que todas as soluções possíveis estão incluídas no programa e são conhecidas.
Em Delphi, a implementação do Adapter é resolvida através de herança onde a classe base (o Target) é abstrata:
type
TWDBManager = class
{ ... }
procedure Connect;virtual;abstract;
procedure BeginTrans;virtual;abstract;
procedure Commit;virtual;abstract;
procedure ExecSQL;virtual;abstract;
procedure OpenSQL;virtual;abstract;
end;
TWBDEMan = class(TWDBManager)
{ ... }
procedure Connect;override;
procedure BeginTrans;override;
procedure Commit;override;
procedure ExecSQL;override;
procedure OpenSQL;override;
end;
TWADOMan = class(TWDBManager)
{ ... }
procedure Connect;override;
procedure BeginTrans;override;
procedure Commit;override;
procedure ExecSQL;override;
procedure OpenSQL;override;
end;
TWDBManager = class
{ ... }
procedure Connect;virtual;abstract;
procedure BeginTrans;virtual;abstract;
procedure Commit;virtual;abstract;
procedure ExecSQL;virtual;abstract;
procedure OpenSQL;virtual;abstract;
end;
TWBDEMan = class(TWDBManager)
{ ... }
procedure Connect;override;
procedure BeginTrans;override;
procedure Commit;override;
procedure ExecSQL;override;
procedure OpenSQL;override;
end;
TWADOMan = class(TWDBManager)
{ ... }
procedure Connect;override;
procedure BeginTrans;override;
procedure Commit;override;
procedure ExecSQL;override;
procedure OpenSQL;override;
end;
O que a classe TWBusinessObj precisa conhecer é apenas a interface - todos os métodos necessários já estão definidos nela:
type
TWBusinessObj = class
{ ... }
_DBMan : TWDBManager;
procedure ExecTransaction;
end;
{ ... }
procedure TWBusinessObj.ExecTransaction;
begin
_DBMan.BeginTrans;
{ outras operações aqui }
_DBMan.Commit;
end;
TWBusinessObj = class
{ ... }
_DBMan : TWDBManager;
procedure ExecTransaction;
end;
{ ... }
procedure TWBusinessObj.ExecTransaction;
begin
_DBMan.BeginTrans;
{ outras operações aqui }
_DBMan.Commit;
end;
Aqui, usei o padrão Adapter para substituir completamente uma tecnologia por outra que estava sendo descontinuada mas não é preciso que o cenário seja tão radical para poder aplicar esse padrão. Pode ser usado também em situações em que o usuário pode optar por uma tecnologia entre várias compatíveis. Por exemplo, numa aplicação de jogo pode-se optar por usar emulação de operações de vídeo ou submetê-las diretamente à placa de vídeo.
Nenhum comentário :
Postar um comentário
OBS: Os comentários enviados a este Blog são submetidos a moderação. Por isso, eles serão publicados somente após aprovação.
Observação: somente um membro deste blog pode postar um comentário.