Salve galera! Tudo bem?

Hoje vamos abordar o pattern Bridge, seus conceitos, usos e exemplos. Vamos lá!

Bridge

Este padrão é utilizado quando queremos separar a abstração da implementação, sendo que, justamente por trabalhar com a forma que interfaces e classes são elaboradas, é considerado um padrão estrutural. Sua aplicação pode ser encontrada em pontes de conexão com bancos de dados JDBC, implementações de renderização gráfica em diferentes plataformas, e até mesmo a implementação de listas do Java.

Este padrão tem as seguintes características que gostaria de destacar:

  • Capacidade de evitar uma ligação permanente entre uma abstração e implementação;
  • Proteção dos clientes com relação a alterações de implementação;
  • Capacidade de esconder completamente uma implementação do cliente;
  • Menor complexidade pra gerenciar hierarquias;

A primeira, capacidade de evitar uma ligação permanente entre uma abstração e implementação, pode ser útil quando desejamos alterar a implementação de uma janela em tempo de execução, como é usado no Windows, por exemplo.

Outro ponto bem interessante, é que o Bridge garante uma proteção aos clientes contra alteração de implementações, já que permite retrocompatibilidade.

Em linguagens como C++ e C#, a capacidade de esconder a implementação completamente permite que a classe esteja inadvertidamente a disposição do cliente.

Permitir a gestão facilitada de um conjunto grande de hierarquias e extensões de uma abstração facilita quando uma abstração que tem muitas extensões e hierarquia, já que o padrão permite uma hierarquia de chamadas generalizada, separando as possíveis implementações.

Abaixo temos o diagrama de classes que exemplifica a estrutura do padrão Bridge:

Acima temos:

  • Abstraction: Esta é uma classe abstrata que contém os membros que definem a abstração de negócios e suas funcionalidades. Contém uma referencia para o objeto do tipo Bridge. Também é responsável por ser a classe base para outras abstrações.
  • Redefined Abstraction: Essa classe herda da classe Abstraction, estendendo a interface definida por ela.
  • Bridge: Esta é uma interface que age como uma ponte entre a classe de abstração e de implementação, e também tem a funcionalidade de tornar a classe de implementação independente da classe de abstração.
  • Implementation A e B: Estas são classes que implementam a interface Bridge e também responsáveis por prover os detalhes de implementação para a abstração associada a ponte.

O código C# para o exemplo acima seria:

Podemos notar que temos uma base, que se mantém fiel a sua estrutura o tempo todo para os clientes, mas que dependendo da ponte associada a propriedade Ponte, podemos ter funcionalidade diferentes sem comprometer o cliente.

Vamos ao resumo do pattern para finalizar com um exemplo mais concreto.

Ficha Resumo

  • Nome: Bridge;
  • Objetivo / intenção: Utilizado quando queremos separar a abstração da implementação, através de uma interface que serve como ponte para as implementações. Muito útil também quando temos uma grande quantidade de hierarquias e extensões para gerenciar;
  • Motivação: Proteger os clientes contra quebras de contrato no uso da abstração e facilitar o gerenciamento de grandes quantidade de hierarquias e extensões em sistemas mais complexos;
  • Aplicabilidade: O padrão Bridge é bastante utilizado em estrutura como pontes para conexões a bancos de dados JDBC, mplementações de renderização gráfica em diferentes plataformas, e uma das mais famosas, a implementação de listas no Java. Com ele os clientes acessam diretamente a abstração sem a necessidade de conhecer qual a implementação, tornando esta totalmente oculta para os clientes e estes protegidos de modificações realizadas nas implementações;
  • Estrutura: Abaixo temos a estrutura UML do pattern, descrita no livro do GoF. Message é uma classe abstrata que contém as propriedades e métodos abstratos para envio de mensagens. Temos duas extensões desta classe, SystemMessage e UserMessage, sendo que UserMessage contém de extra a propriedade UserComments, agregando uma funcionalidade extra. Temos uma interface IMessageSender, interface referenciada na propriedade MessageSender da classe abstrata Message, e as implementações EmailSender, WebServiceSender e MSMQSender, que são diferentes implementações de IMessageSender.
    A classe Message, assim como suas extensões, irão utilizar a interface IMessageSender para envio da mensagem, podendo estes serem informados através de configurações, injeção de dependência, etc.;
  • Consequências: O padrão Bridge facilita quando temos uma quantidade grande de hierarquias e extensões, facilitando o uso das implementações, isolando elas do cliente, assim como uma melhor separação entre abstração e implementação. Em contrapartida, temos um aumento considerável na quantidade e complexidade do código, dada a criação de várias classes adicionais;
  • Implementações: Abaixo temos um exemplo de código para a estrutura de classes descrita no diagrama em “Estrutura”:
  • Usos conhecidos: Muito utilizado na definição sistemas de renderização gráfica multi-plataforma, pontes de conexões de bancos de dados JDBC e o mais famoso, a implementação de listas do Java;
  • Padrões relacionados: Adapter, Strategy e Template Method;

Concluindo

Este foi o padrão Bridge, geralmente utilizado quando temos hierarquias muito grandes e queremos separar a abstração da implementação, sem comprometer os clientes, protegendo eles de mudanças nas implementações.

Na próxima parte desta série, vamos abordar o padrão Decorator.

Aguardo feedbacks e dúvidas de vocês, seja aqui no Medium ou através das redes sociais.

E teremos a segunda parte da série “Criando uma aplicação completa com Blazor” até segunda-feira, 1/10, mas quero liberar o post o quanto antes. Fiquem ligados.

Um abraço!