Design Patterns: Padrões Comportamentais
Aplicando boas práticas para criação de objetos
Em
que situação o tema é útil
Padrões
de projeto estruturais são úteis para criar softwares mais fáceis de serem
mantidos, evoluídos, promovendo reutilização de código, uso de boas práticas de
programação orientada a objetos, redução de custos com manutenção, já que
permitem que alterações em um determinado sistema não quebrem outras
funcionalidades, reduzindo a dependência entre classes, através do uso
exaustivo de abstrações. Dos padrões tratados neste artigo, o Adapter serve
para permitir a comunicação entre duas classes com interfaces distintas; Bridge
serve para separar totalmente a interface de um objeto de sua implementação
concreta; Composite permite criar composições de objetos; Decorator permite
adicionar funcionalidades a um objeto sem usar herança estática, usando herança
de “caixa-preta”, através da implementação por delegação; Façade ajuda a tornar
um subsistema de classes mais fácil de utilizar. Como na edição anterior,
primeiramente será apresentada uma descrição formal de cada padrão segundo GoF,
depois um exemplo prático em Delphi.
Adapter
A intenção do padrão Adapter, também conhecido como Wrapper, é converter a interface de uma classe em outra interface esperada pelos clientes. Permite que classes trabalhem em conjunto, pois de outra forma não poderiam, devido ao fato de terem interfaces incompatíveis. O padrão pode ser usado quando se quiser usar uma classe existente, mas sua interface não corresponder à interface que necessita; ou quando quiser criar uma classe reutilizável que coopere com classes não relacionadas ou não previstas, ou seja, classes que não necessariamente tenham interfaces compatíveis; você precisa usar várias subclasses existentes, porém, quando for impraticável adaptar essas interfaces criando subclasses para cada uma. O padrão traz alguns benefícios. Um adaptador de classe adapta Adaptee a Target através do uso efetivo de uma classe Adapter concreta, com isso, permite a Adapter substituir algum comportamento do Adaptee, uma vez que Adapter é uma subclasse de Adaptee. Um adaptador de objeto permite que um único Adapter trabalhe com muitos Adaptees. O Adapter também pode acrescentar funcionalidades a todos os Adaptees de uma só vez.
Os participantes do padrão de projeto são:
· Target – define a interface específica do domínio que o Client usa;
· Client – colabora com objetos compatíveis com a interface de Target;
· Adaptee – define uma interface existente que necessita ser adaptada;
· Adapter – adapta a interface do Adaptee à interface do Target;
Para entender melhor o padrão Adapter, vamos recorrer a alguns objetos do mundo real. Por exemplo, digamos que quiséssemos conectar nosso notebook em uma tomada para recarregar sua bateria. Ao entrar em uma sala e encontrar um ponto livre, reparamos que a tomada fêmea segue o novo padrão brasileiro NBR 14136, enquanto nosso notebook tem um cabo com plug macho no padrão norte americano NEMA 5. Ou seja, estamos com problemas para conectar dois objetos, pois eles possuem interfaces incompatíveis. A solução para este problema no mundo real é fácil de ser resolvida, precisamos de um Adaptador, ou Adapter. Ele vai se encarregar de converter o a interface do Adaptee (o plug do nosso notebook) em um formato que o Target entenda (o alvo, a tomada, onde realmente queremos conectar). A Figura 1 mostra um exemplo de como seriam nossos personagens do padrão de projeto em objetos do mundo real.
Figura 1. Adaptador no mundo real conecta duas interfaces distintas
No mundo orientado a objetos, um Adapter é frequentemente encontrado em muitas situações. No Delphi, por exemplo, temos dezenas de aplicações deste padrão. Vamos observar a arquitetura do novo DataSnap. No modelo antigo do DataSnap (e primeiras versões do MIDAS), tínhamos um componente de conexão remoto para cada tipo de protocolo que nosso servidor de aplicação pudesse trabalhar. Por exemplo, um DCOMConnection era utilizado no cliente para conectar a um servidor DCOM, MTS ou COM+. A partir do Delphi 6, com o suporte a Web Services, foi possível utilizar um SOAPConnection para conectar em um servidor de aplicação baseado em SOAP (Simple Object Access Protocol). E poderíamos citar outros tipos de conexão, como CorbaConnection, WebConnection, SocketConnection e etc. Um ClientDataSet pode então se conectar a qualquer um desses componentes concretos para obter dados de diferentes tipos de servidores, independente do protocolo que usem. Para isso, basta aponta-los para a propriedade RemoteServer de ClientDataSet (Figura 2), que é do tipo TCustomRemoteServer, classe base para todos os componentes de conexão (SOAPConnection, DCOMConnection, SocketConnection, WebConnection, CorbaConnection etc.). Com o novo DataSnap, do Delphi 2009 em diante, uma grande mudança foi feita, ao invés de termos um componente com uma implementação concreta para cada protocolo de comunicação DataSnap, passamos a usar um único componente de conexão, o próprio SQLConnection do DBExpress. O código de acesso dependente de protocolo passou a residir então em um driver do DBExpress (DLL). Agora vem o problema, se tentarmos conectar um ClientDataSet em um SQLConnection pela propriedade RemoteServer, o que acontece? O SQLConnection nem aparece na lista, pois este descende de TCustomConnection, e não de TCustomRemoteServer. Como é impossível usar herança múltipla no Delphi, pelo menos de forma estática, não há uma forma de resolver o problema sem causar uma mudança profunda na VCL, modificar a classe base de um dos tipos citados, o que iria ferir princípios fundamentais da orientação a objetos (e uma reação em cadeia de alterações em todo framework). Então, um padrão de projeto foi aplicado para resolver o problema de forma elegante. A classe TDSProviderConnection funciona como uma “ponte” entre um ClientDataSet e um SQLConnection, fazendo com que o SQLConnection “finja” ser um RemoteServer para o ClientDataSet ( ...
Confira outros conteúdos:
Perguntas frequentes
Nossos casos de sucesso
Eu sabia pouquíssimas coisas de programação antes de começar a estudar com vocês, fui me especializando em várias áreas e ferramentas que tinham na plataforma, e com essa bagagem consegui um estágio logo no início do meu primeiro período na faculdade.
Estudo aqui na Dev desde o meio do ano passado!
Nesse período a Dev me ajudou a crescer muito aqui no trampo.
Fui o primeiro desenvolvedor contratado pela minha
empresa. Hoje eu lidero um time de desenvolvimento!
Minha meta é continuar estudando e praticando para ser um
Full-Stack Dev!
Economizei 3 meses para assinar a plataforma e sendo sincero valeu muito a pena, pois a plataforma é bem intuitiva e muuuuito didática a metodologia de ensino. Sinto que estou EVOLUINDO a cada dia. Muito obrigado!
Nossa! Plataforma maravilhosa. To amando o curso de desenvolvimento front-end, tinha coisas que eu ainda não tinha visto. A didática é do jeito que qualquer pessoa consegue aprender. Sério, to apaixonado, adorando demais.
Adquiri o curso de vocês e logo percebi que são os melhores do Brasil. É um passo a passo incrível. Só não aprende quem não quer. Foi o melhor investimento da minha vida!
Foi um dos melhores investimentos que já fiz na vida e tenho aprendido bastante com a plataforma. Vocês estão fazendo parte da minha jornada nesse mundo da programação, irei assinar meu contrato como programador graças a plataforma.
Wanderson Oliveira
Comprei a assinatura tem uma semana, aprendi mais do que 4 meses estudando outros cursos. Exercícios práticos que não tem como não aprender, estão de parabéns!
Obrigado DevMedia, nunca presenciei uma plataforma de ensino tão presente na vida acadêmica de seus alunos, parabéns!
Eduardo Dorneles
Aprendi React na plataforma da DevMedia há cerca de 1 ano e meio... Hoje estou há 1 ano empregado trabalhando 100% com React!
Adauto Junior
Já fiz alguns cursos na área e nenhum é tão bom quanto o de vocês. Estou aprendendo muito, muito obrigado por existirem. Estão de parabéns... Espero um dia conseguir um emprego na área.