Qual é a diferença entre os padrões Bridge e Adapter?
Qual é a diferença entre os padrões Bridge e Adapter?
Respostas:
"O adaptador faz as coisas funcionarem depois de projetadas; o Bridge as faz funcionar antes de serem. [GoF, p219]"
Efetivamente, o padrão do Adaptador é útil quando você possui código existente, seja de terceiros ou interno, mas fora do seu controle ou não é mutável para atender perfeitamente à interface que você precisa. Por exemplo, temos um SuperWeaponsArray que pode controlar uma boa variedade de dispositivos do dia do juízo final.
public class SuperWeaponsArray {
/*...*/
public void destroyWorld() {
for (Weapon w : armedWeapons) {
w.fire();
}
}
}
Ótimo. Exceto que percebemos que temos um dispositivo nuclear em nosso arsenal que antecede amplamente a conversão para a interface de armas. Mas nós realmente gostaríamos que funcionasse aqui ... então o que fazemos?
NukeWeaponsAdaptor - baseado em nossa classe Nuke, mas exportando a interface Arma. Doce, agora podemos certamente destruir o mundo. Parece um pouco de confusão, mas faz as coisas funcionarem.
O padrão Bridge é algo que você implementa antecipadamente - se você sabe que possui duas hierarquias ortogonais, ele fornece uma maneira de dissociar a interface e a implementação de tal maneira que você não obtém um número insano de classes. Digamos que você tenha:
Tipos de objetos de arquivo MemoryMappedFile e DirectReadFile. Digamos que você queira ler arquivos de várias fontes (talvez implementações Linux vs. Windows, etc.). O Bridge ajuda a evitar que você acabe com:
MemoryMappedWindowsFile MemoryMappedLinuxFile DirectReadWindowsFile DirectReadLinuxFile
http://en.wikipedia.org/wiki/Adapter_pattern
O padrão do adaptador é mais sobre como fazer com que seu código existente funcione com um sistema ou interface mais recente.
Se você possui um conjunto de APIs de serviço da web padrão da empresa que gostaria de oferecer à interface de extensibilidade existente de outro aplicativo, considere escrever um conjunto de adaptadores para fazer isso. Observe que há uma área cinza e isso é mais sobre como você define tecnicamente o padrão, pois outros padrões como a fachada são semelhantes.
http://en.wikipedia.org/wiki/Bridge_pattern
O padrão Bridge permitirá que você possua implementações alternativas de um algoritmo ou sistema.
Embora não seja um exemplo clássico de padrão de ponte, imagine se você tivesse algumas implementações de um armazenamento de dados: uma é eficiente no espaço, a outra é eficiente no desempenho bruto ... e você tem um caso de negócios para oferecer tanto no aplicativo quanto na estrutura .
Em termos de sua pergunta, "onde posso usar qual padrão", a resposta é: onde quer que faça sentido para o seu projeto! Talvez considere oferecer uma edição de esclarecimentos para orientar a discussão sobre onde você acredita que precisa usar um ou outro.
Adaptador:
Diagrama UML: do artigo dofactory :
Alvo : define a interface específica do domínio que o Cliente usa.
Adaptador : adapta a interface Adaptado à interface de destino.
Adaptado : define uma interface existente que precisa ser adaptada .
Cliente : colabora com objetos em conformidade com a interface Target.
Exemplo:
Quadrado e Retângulo são duas formas diferentes e a área de obtenção () de cada uma delas exige métodos diferentes. Mas ainda assim o Square trabalha na interface Retangular com a conversão de algumas das propriedades.
public class AdapterDemo{
public static void main(String args[]){
SquareArea s = new SquareArea(4);
System.out.println("Square area :"+s.getArea());
}
}
class RectangleArea {
public int getArea(int length, int width){
return length * width;
}
}
class SquareArea extends RectangleArea {
int length;
public SquareArea(int length){
this.length = length;
}
public int getArea(){
return getArea(length,length);
}
}
Ponte:
EDIT: (conforme sugestão @quasoft)
Você tem quatro componentes neste padrão.
Abstração : define uma interface
RefinedAbstraction : Implementa abstração:
Implementador : define uma interface para implementação
ConcreteImplementor : Implementa a interface do implementador.
Fragmento de código:
Gear gear = new ManualGear();
Vehicle vehicle = new Car(gear);
vehicle.addGear();
gear = new AutoGear();
vehicle = new Car(gear);
vehicle.addGear();
Post relacionado:
Quando você usa o padrão de ponte? Como é diferente do padrão do adaptador?
Principais diferenças: do artigo de criação de código - fonte
Este post já existe há algum tempo. No entanto, é importante entender que uma fachada é um pouco semelhante a um adaptador, mas não é exatamente a mesma coisa. Um adaptador "adapta" uma classe existente a uma classe cliente geralmente não compatível. Digamos que você tenha um sistema de fluxo de trabalho antigo que seu aplicativo está usando como cliente. Sua empresa poderia substituir o sistema de fluxo de trabalho por um novo "incompatível" (em termos de interfaces). Na maioria dos casos, você pode usar o padrão do adaptador e escrever um código que realmente chama as interfaces do novo mecanismo de fluxo de trabalho. Uma ponte é geralmente usada de uma maneira diferente. Se você realmente possui um sistema que precisa trabalhar com sistemas de arquivos diferentes (por exemplo, disco local, NFS etc.), pode usar o padrão de ponte e criar uma camada de abstração para trabalhar com todos os seus sistemas de arquivos. Basicamente, esse seria um caso de uso simples para o padrão de ponte. A Fachada e o adaptador compartilham algumas propriedades, masfachadas são geralmente usadas para simplificar uma interface / classe existente . Nos primeiros dias dos EJBs, não havia chamadas locais para EJBs. Os desenvolvedores sempre obtinham o esboço, o reduziam e o chamavam de "pseudo-remotamente". Isso muitas vezes causava problemas de desempenho (especialmente quando realmente chamado por fio). Desenvolvedores experientes usariam o padrão de fachada para fornecer uma interface de granulação mais grossa para o cliente. Essa fachada, por sua vez, fazia várias chamadas para diferentes métodos mais refinados. Em suma, isso reduziu bastante o número de chamadas de método necessárias e aumentou o desempenho.
Bridge é um adaptador aprimorado. O Bridge inclui adaptador e adiciona flexibilidade adicional a ele. Aqui está como os elementos da resposta de Ravindra são mapeados entre os padrões:
Adapter | Bridge
-----------|---------------
Target | Abstraction
-----------|---------------
| RefinedAbstraction
|
| This element is Bridge specific. If there is a group of
| implementations that share the same logic, the logic can be placed here.
| For example, all cars split into two large groups: manual and auto.
| So, there will be two RefinedAbstraction classes.
-----------|---------------
Adapter | Implementor
-----------|---------------
Adaptee | ConcreteImplementor
Na resposta principal, @James cita uma frase do GoF, página 219. Acho que vale a pena reproduzir a explicação completa aqui.
Adaptador versus Bridge
Os padrões do adaptador e da ponte têm alguns atributos comuns. Ambos promovem flexibilidade, fornecendo um nível de indireção para outro objeto. Ambos envolvem encaminhamento de pedidos para esse objeto a partir de uma interface diferente da sua.
A principal diferença entre esses padrões reside em suas intenções. O adaptador se concentra na resolução de incompatibilidades entre duas interfaces existentes. Ele não se concentra em como essas interfaces são implementadas, nem considera como elas podem evoluir independentemente. É uma maneira de fazer com que duas classes projetadas independentemente funcionem juntas, sem reimplementar uma ou outra. Bridge, por outro lado, une uma abstração e suas (potencialmente numerosas) implementações. Ele fornece uma interface estável para os clientes, ao mesmo tempo em que permite variar as classes que o implementam. Também acomoda novas implementações à medida que o sistema evolui.
Como resultado dessas diferenças, o Adapter e o Bridge são frequentemente usados em diferentes pontos do ciclo de vida do software. Um adaptador geralmente se torna necessário quando você descobre que duas classes incompatíveis devem funcionar juntas, geralmente para evitar a replicação do código. O acoplamento é imprevisto. Por outro lado, o usuário de uma ponte entende de antemão que uma abstração deve ter várias implementações e ambas podem evoluir independentemente. O padrão do adaptador faz as coisas funcionarem após serem projetadas; Bridge os faz trabalhar antes deles. Isso não significa que o adaptador seja de alguma forma inferior ao Bridge; cada padrão apenas trata de um problema diferente.
Suponha que você tenha uma classe Shape abstrata com uma funcionalidade de desenho (genérica / abstrata) e um Circle que implementa a Shape. O padrão de ponte é simplesmente uma abordagem de abstração bidirecional para dissociar a implementação (desenho em Círculo) e a funcionalidade genérica / abstrata (desenho na classe Forma).
O que isso realmente significa? À primeira vista, parece algo que você já está fazendo (por inversão de dependência). Portanto, não se preocupe em ter uma base de código menos modular ou mais modular. Mas é uma filosofia um pouco mais profunda por trás disso.
Pelo que entendi, a necessidade do padrão de uso pode surgir quando eu precisar adicionar novas classes que estão intimamente relacionadas ao sistema atual (como RedCircle ou GreenCircle) e que diferem apenas por uma única funcionalidade (como cor). E precisarei do padrão Bridge, especialmente se as classes de sistema existentes (Circle ou Shape) forem alteradas com frequência e você não quiser que as classes recém-adicionadas sejam afetadas por essas alterações. É por isso que a funcionalidade genérica do desenho é abstraída para uma nova interface, para que você possa alterar o comportamento do desenho independentemente de Shape ou Circle.