Entendendo os padrões de projeto a partir da análise de frameworks populares de mercado: Padrões estruturais

Estructural Gof Design Patterns

Enquanto no artigo anterior observamos algumas aplicações populares de padrões de projeto criacionais e como que eles definem melhores maneiras de se instanciar objetos agregando a inteligência de como dependências e propriedades se interrelacionam de forma a originar novos objetos,  nesta sequencia demonstrarei algumas aplicações de padrões de projeto estruturais.

Mas o que são e do que tratam padrões de projeto estruturais? Em resumo, são abstrações que exemplificam mecanismos inteligentes de organização de entidades de um determinado sistema de maneira a descrever como que os objetos e classes poderiam ser combinados para formar estruturas maiores.  São modelos que, em geral, lidam com a responsabilidade de definir as relações entre classes e objetos com o propósito de obter uma determinada nova funcionalidade e que são organizados em sete principais grupos: adapter pattern, bridge pattern, composite pattern, decorator pattern, façade pattern, flyweight pattern e, por fim, proxy pattern dos quais veremos algumas aplicações reais em seguida:

  1. Adapter diz respeito à abstração que resolve o problema de incompatibilidade entre interfaces distintas, tornando possível que elas trabalhem de forma colaborativa. Uma maneira bastante simples de se pensar sobre esse padrão é imaginar os adaptadores de tomada que permitem que diferentes padrões se comuniquem de forma a distribuir energia independentemente da interface da tomada. Por exemplo, o java.io.InpuStreamReader, que recebe uma cadeia de bytes (InputStream) e as adapta para caracteres (Reader).

  2. Bridge é um padrão intimamente relacionado ao anterior. A diferença entre ambos é que no segundo a conexão se dá por meio de abstrações e implementações fixas, o que não ocorre no primeiro. O objetivo principal do Bridge não é somente permitir que interfaces diferentes se comuniquem, mas principalmente trata de abstrair um modelo pelo qual diferentes abstrações e implementações possam variar independentemente umas das outras. Esse é o motivo pelo qual frequentemente está relacionado ao uso de drivers. Por exemplo, conexões com o banco de dados que fazem uso de drivers JDBC devem funcionar para diferentes sistemas operacionais ao mesmo tempo em que operam em diferentes bancos de dados.

  3. Composite é um padrão que compõe objetos em uma estrutura de árvore para representar uma hierarquia do tipo parte de um todo. A partir desse padrão se torna simples a tarefa de lidar com objetos únicos ou com composição de objetos, pois ambos serão trados de maneira uniforme, ignorando suas diferenças. Um exemplo simples seria o do java.util.List com o método addAll(Collection).

  4. Decorator é um padrão que permite estender uma funcionalidade usando composição em detrimento de herança, ou seja, ele fornece uma alternativa flexível a subclasses para extensão de funcionalidades. Geralmente são constituídos de uma classe que implementa uma interface, mas que ao mesmo tempo a recebe como instância em seus métodos construtores. Um exemplo de aplicação real desse modelo é a classe FilterInputStream que recebe um objeto InputStream em seu método construtor e o “decora”.

  5. Façade (ou fachada) é um padrão que centraliza em uma única interface um conjunto de interfaces. Ele abstrai em um modelo de alto nível a necessidade de interação entre várias representações internas. Em geral é reconhecido por um método comportamental que quando invocado interage com diferentes instâncias, como o javax.faces.context.FacesContext, que dentro dele se comunica com LifeCycle, ViewHandler e NavigationHandler entre outros tipos pelos quais o usuário final não precisa se preocupar.

  6. Flyweight é uma opção para se trabalhar, de forma eficiente, com grandes quantidades de objetos de granularidade fina a partir do uso de compartilhamento de dados entre eles. O método Java.lang.Integer.valueOf(int) é um exemplo de aplicação desse padrão que pode melhorar bastante a performance da requisição de objetos Integer para um int em situações nas quais esses valores são requisitados frequentemente, pois faz uso de cache interno.

  7. Proxy é um padrão desenhado para postergar todo o custo de processamento da criação e inicialização de um objeto até que ele realmente seja preciso, tornando assim o sistema mais eficiente. Para isso, ele fornece um objeto substituto ao verdadeiro que possui uma interface idêntica a original e que gerencia a chamada ao verdadeiro. Essa é a intenção da classe java.lang.reflect.Proxy

É isso! Esses foram alguns exemplos de aplicações de padrões de projeto estruturais em sistemas reais e bastante usados e, na sequência, lidaremos com os padrões de projeto comportamentais!

Artigos relacionados:

Referências


Anúncios