Difference between Bridge pattern and Adapter pattern
"Adapter makes things work after they're designed; Bridge makes them work before they are. [GoF, p219]"
Effectively, the Adapter pattern is useful when you have existing code, be it third party, or in-house, but out of your control, or otherwise not changeable to quite meet the interface you need it to. For instance, we have a SuperWeaponsArray which can control a fine array of doomsday devices.
public class SuperWeaponsArray {
/*...*/
public void destroyWorld() {
for (Weapon w : armedWeapons) {
w.fire();
}
}
}
Great. Except we realize we have a nuclear device in our arsenal that vastly predates the conversion to the Weapon interface. But we'd really like it to work here... so what do we do... wedge it in!
NukeWeaponsAdaptor - based off of our Nuke class, but exporting the Weapon interface. Sweet, now we can surely destroy the world. It seems like bit of a kludge, but it makes things work.
The Bridge pattern is something you implement up front - if you know you have two orthogonal hierarchies, it provides a way to decouple the interface and the implementation in such a way that you don't get an insane number of classes. Let's say you have:
MemoryMappedFile and DirectReadFile types of file objects. Let's say you want to be able to read files from various sources (Maybe Linux vs. Windows implementations, etc.). Bridge helps you avoid winding up with:
MemoryMappedWindowsFile MemoryMappedLinuxFile DirectReadWindowsFile DirectReadLinuxFile
Adapter:
- It is a structural pattern
- It is useful to work with two incompatible interfaces
UML Diagram: from dofactory article:
Target : defines the domain-specific interface that Client uses.
Adapter : adapts the interface Adaptee to the Target interface.
Adaptee : defines an existing interface that needs adapting.
Client : collaborates with objects conforming to the Target interface.
Example:
Square and Rectangle are two different shapes and getting area() of each of them requires different methods. But still Square work on Rectangle interface with conversion of some of the properties.
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);
}
}
Bridge:
- It is structural pattern
- it decouples an abstraction from its implementation and both can vary independently
- It is possible because composition has been used in place of inheritance
EDIT: ( as per @quasoft suggestion)
You have four components in this pattern.
Abstraction: It defines an interface
RefinedAbstraction: It implements abstraction:
Implementor: It defines an interface for implementation
ConcreteImplementor: It implements Implementor interface.
Code snippet:
Gear gear = new ManualGear();
Vehicle vehicle = new Car(gear);
vehicle.addGear();
gear = new AutoGear();
vehicle = new Car(gear);
vehicle.addGear();
Related post:
When do you use the Bridge Pattern? How is it different from Adapter pattern?
Key differences: from sourcemaking article
- Adapter makes things work after they're designed; Bridge makes them work before they are.
- Bridge is designed up-front to let the abstraction and the implementation vary independently. Adapter is retrofitted to make unrelated classes work together.