Eu não entendo o padrão de design da "ponte". Passei por vários sites, mas eles não ajudaram.
Alguém pode me ajudar a entender isso?
Eu não entendo o padrão de design da "ponte". Passei por vários sites, mas eles não ajudaram.
Alguém pode me ajudar a entender isso?
Respostas:
No POO, usamos polimorfismo para que uma abstração possa ter várias implementações. Vejamos o seguinte exemplo:
Um novo requisito foi introduzido e precisa trazer a perspectiva de aceleração dos trens; portanto, altere o código conforme abaixo.
O código acima não é sustentável e não pode ser reutilizado (supondo que possamos reutilizar o mecanismo de aceleração para a mesma plataforma de trilhos). O código a seguir aplica o padrão de ponte e separa as duas abstrações diferentes, transporte de trem e aceleração .
fonte
Monorail
já que não são realmente duas palavras, é uma única palavra (composta). Um MonoRail seria uma subclasse de Rail em vez de um tipo diferente de Rail (que é). Assim como não seria utilizarSunShine
ouCupCake
, eles seriamSunshine
eCupcake
Embora a maioria dos padrões de design tenha nomes úteis, acho que o nome "Bridge" não é intuitivo em relação ao que faz.
Conceitualmente, você envia os detalhes da implementação usados por uma hierarquia de classes para outro objeto, normalmente com sua própria hierarquia. Ao fazer isso, você está removendo uma forte dependência desses detalhes de implementação e permitindo que os detalhes dessa implementação sejam alterados.
Em pequena escala, comparo isso ao uso de um padrão de estratégia na maneira como você pode conectar um novo comportamento. Mas, em vez de apenas agrupar um algoritmo, como geralmente é visto em uma estratégia, o objeto de implementação geralmente é mais preenchido. E quando você aplica o conceito a uma hierarquia de classes inteira, o padrão maior se torna uma Bridge. (Novamente, odeie o nome).
Não é um padrão que você usará todos os dias, mas achei útil ao gerenciar uma possível explosão de classes que pode acontecer quando você tem uma necessidade (aparente) de herança múltipla.
Aqui está um exemplo do mundo real:
Eu tenho uma ferramenta RAD que permite soltar e configurar controles em uma superfície de design, então eu tenho um modelo de objeto como este:
E assim por diante, com talvez uma dúzia de controles.
Mas, em seguida, um novo requisito é adicionado para oferecer suporte a vários temas (aparência). Vamos dizer que temos os seguintes temas:
Win32
,WinCE
,WinPPC
,WinMo50
,WinMo65
. Cada tema teria valores ou implementações diferentes para operações relacionadas à renderização, como DefaultFont, DefaultBackColor, BorderWidth, DrawFrame, DrawScrollThumb, etc.Eu poderia criar um modelo de objeto como este:
etc., para um tipo de controle
etc., um para o outro tipo de controle (novamente)
Você entendeu a idéia - você obtém uma explosão de classe do número de widgets vezes o número de temas. Isso complica o designer da RAD, tornando-o ciente de todos os temas. Além disso, adicionar novos temas força o designer do RAD a ser modificado. Além disso, há muita implementação comum em um tema que seria ótimo herdar, mas os controles já estão herdando de uma base comum (
Widget
).Então, em vez disso, o que fiz foi criar uma hierarquia de objetos separada que implementa o tema. Cada widget manteria uma referência ao objeto que implementa as operações de renderização. Em muitos textos, essa classe possui um sufixo,
Impl
mas eu me desviei dessa convenção de nomenclatura.Então agora minha
TextboxWidget
aparência fica assim:E posso fazer com que meus vários pintores herdem minha base específica de tema, o que eu não podia fazer antes:
Uma das coisas boas é que posso carregar dinamicamente as implementações em tempo de execução, permitindo adicionar tantos temas quanto eu quiser, sem alterar o software principal. Em outras palavras, minha "implementação pode variar independentemente da abstração".
fonte
Win32TextboxPainter
eWin32ListPainter
deWin32WidgetPainter
. Você pode ter uma árvore de herança no lado da aplicação, mas deve ser mais genérico (talvezStaticStyleControlPainter
,EditStyleControlPainter
eButtonStyleControlPainter
) com quaisquer operações primitivas necessários substituídas conforme necessário. Isso está mais próximo do código real em que eu estava baseando o exemplo.A ponte pretende desacoplar uma abstração de sua implementação concreta , para que ambas possam variar independentemente:
A ponte consegue isso usando a composição:
Comentários adicionais sobre uma confusão frequente
Esse padrão é muito semelhante ao padrão do adaptador: a abstração oferece uma interface diferente para uma implementação e usa a composição para fazer isso. Mas:
Neste excelente livro seminal sobre padrões de design, os autores também observam que:
fonte