Bridge é um padrão de projeto estrutural que visa desacoplar uma abstração de sua implementação, de forma que permita que ambos evoluam de forma independente.

O uso desse padrão é recomendado ao lidar com classes que possuem muitas implementações diferentes e usam herança para implementar a abstração. Nesses casos, a herança conecta uma implementação à abstração permanentemente, de forma que é difícil modificar, aumentar e reutilizar as abstrações de forma independente.

Para dar um exemplo ilustrado, vamos fingir que temos um cenário onde queremos criar diferentes tipos de contas bancárias: CheckingAccount e SavingsAccount. Queremos que nosso sistema seja flexível para a criação de novos tipos de contas, então criamos uma classe abstrata chamada BankAccount e estendemos esta classe com as classes CheckingAccount e SavingsAccount.

Ótimo! Mais tarde, queremos dar aos nossos tipos de conta seu próprio tipo de cartão de crédito personalizado. Criamos as classes BasicCreditCard, SilverCreditCard e GoldCreditCard. Ao vincular esses cartões de crédito a cada tipo de conta bancária, o problema fica claro:



A abordagem ingênua seria criar uma combinação para cada tipo de conta, uma solução que é cara e cresce exponencialmente (imagine o tanto de trabalho se adicionarmos um novo tipo de conta!). O código também é altamente acoplado, pois estados e comportamentos diferentes estariam contidos em uma única classe.

O padrão Bridge resolve esse problema mudando de herança para composição e realocando todas as classes CreditCard para sua própria hierarquia. Ao fazer isso, permitimos que ambos os contextos evoluam e mudem independentemente.



Com esse design em mente, vamos então criar nossa interface CreditCard:



Agora, vamos criar nossos tipos: Basic, Silver e Gold, todos implementando os métodos especificados pela interface CreditCard.





Vamos criar a abstração BankAccount, a classe base para nossos tipos de conta. Esta classe terá um objeto CreditCard, bem como um método para obter as informações do cartão.



Com tudo criado, podemos escrever nossos tipos de conta CheckingAccount e SavingsAccount:




Para testar nosso projeto, criaremos uma classe principal inicializando cada conta com seus respectivos tipos de cartão de crédito.



…que gera o seguinte conteúdo:



No fim das contas, o padrão Bridge é uma ótima ferramenta para ser utilizada quando queremos dividir e refatorar classes com muitas variantes, e também quando precisamos estender uma classe em dimensões independentes. Um grande benefício em usar esse padrão é que ele segue o princípio aberto/fechado (já que podemos adicionar abstrações e implementações sem afetar as existentes) e o princípio de responsabilidade única.

Você pode verificar a implementação completa deste exemplo aqui no meu Github: GracieleDamasceno/design-patterns!

Referências:

Bridge Pattern - Refactoring Guru

Design Patterns (2005), By Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides, Craig Larman