As GOF says what you do by using this pattern is "Decouple an abstraction from its implementation so that the two can vary independently."
If I explain it further, in Bridge Design Pattern you decouple a functionality from a class hierarchy and create another interface and a class hierarchy which support that functionality and then create a bridge between these two hierarchies by creating a "has-a" relationship between two interfaces.
You will not understand this at once. But after carefully reading this lesson you will get a good understanding.
As usual Ill take our Vehicle interface to explain this pattern.
Assume that you have an interface called Vehicle which contains createVehicle() method.
public interface Vehicle {
public void createVehicle();
}
public void createVehicle();
}
Think that you need to have four types of vehicles. Those are Black Car, White Car, Back Motorbike and White Motorbike. So you will simply create below four classes which implements Vehicle interface.
public class BlackCar implements Vehicle {
@Override
public void createVehicle() {
installCarParts();
paintInBlack();
}
private void paintInBlack() {
System.out.println("Painting in black...");
}
private void installCarParts() {
System.out.println("Installing car parts...");
}
}
public class WhiteCar implements Vehicle {
@Override
public void createVehicle() {
installCarParts();
paintInBlack();
}
private void paintInBlack() {
System.out.println("Painting in white...");
}
private void installCarParts() {
System.out.println("Installing car parts...");
}
}
public class BlackMotorbike implements Vehicle {
@Override
public void createVehicle() {
installCarParts();
paintInBlack();
}
private void paintInBlack() {
System.out.println("Painting in black...");
}
private void installCarParts() {
System.out.println("Installing motorbike parts...");
}
}
public class WhiteMotorbike implements Vehicle {
@Override
public void createVehicle() {
installCarParts();
paintInBlack();
}
private void paintInBlack() {
System.out.println("Painting in white...");
}
private void installCarParts() {
System.out.println("Installing motorbike parts...");
}
}
@Override
public void createVehicle() {
installCarParts();
paintInBlack();
}
private void paintInBlack() {
System.out.println("Painting in black...");
}
private void installCarParts() {
System.out.println("Installing car parts...");
}
}
public class WhiteCar implements Vehicle {
@Override
public void createVehicle() {
installCarParts();
paintInBlack();
}
private void paintInBlack() {
System.out.println("Painting in white...");
}
private void installCarParts() {
System.out.println("Installing car parts...");
}
}
public class BlackMotorbike implements Vehicle {
@Override
public void createVehicle() {
installCarParts();
paintInBlack();
}
private void paintInBlack() {
System.out.println("Painting in black...");
}
private void installCarParts() {
System.out.println("Installing motorbike parts...");
}
}
public class WhiteMotorbike implements Vehicle {
@Override
public void createVehicle() {
installCarParts();
paintInBlack();
}
private void paintInBlack() {
System.out.println("Painting in white...");
}
private void installCarParts() {
System.out.println("Installing motorbike parts...");
}
}
You see that this is not the best design. For an example your paintInBlack() and paintInWhite() methods are duplicated. This design becomes more complex and less maintainable when the number of implementation classes are higher.
In this kind of situations Bridge Pattern comes to your help.
In Bridge Pattern what you do is create another interface(Painter) which does the painting job and then create another hierarchy of classes which implements this interface. Then you keep a reference to the Painter interface in Vehicle interface.
Now you have two class hierarchies which implement separate two interfaces. Having a reference to Painter interface in Vehicle interface is the bridge between these two hierarchies.
This is the Bridge Design Pattern.
With this pattern, your interfaces and implementation classes will be as below.
public abstract class Vehicle {
protected Paint painter;
public abstract void createVehicle();
}
public class Car extends Vehicle {
public Car(Paint painter) {
this.painter = painter;
}
@Override
public void createVehicle() {
installCarParts();
painter.paint();
}
private void installCarParts() {
System.out.println("Installing car parts...");
}
}
public class Motorbike extends Vehicle {
public Motorbike(Paint painter) {
this.painter = painter;
}
@Override
public void createVehicle() {
installMotorbikeParts();
painter.paint();
}
private void installMotorbikeParts() {
System.out.println("Installing motorbike parts...");
}
}
public interface Paint {
public void paint();
}
public class BlackPaint implements Paint {
@Override
public void paint() {
System.out.println("Painting in black...");
}
}
public class WhitePaint implements Paint {
@Override
public void paint() {
System.out.println("Painting in white...");
}
}
protected Paint painter;
public abstract void createVehicle();
}
public class Car extends Vehicle {
public Car(Paint painter) {
this.painter = painter;
}
@Override
public void createVehicle() {
installCarParts();
painter.paint();
}
private void installCarParts() {
System.out.println("Installing car parts...");
}
}
public class Motorbike extends Vehicle {
public Motorbike(Paint painter) {
this.painter = painter;
}
@Override
public void createVehicle() {
installMotorbikeParts();
painter.paint();
}
private void installMotorbikeParts() {
System.out.println("Installing motorbike parts...");
}
}
public interface Paint {
public void paint();
}
public class BlackPaint implements Paint {
@Override
public void paint() {
System.out.println("Painting in black...");
}
}
public class WhitePaint implements Paint {
@Override
public void paint() {
System.out.println("Painting in white...");
}
}
In your client class now you can create various types of vehicles as below.
public class Test {
public static void main(String[] args) {
Car whiteCar = new Car(new WhitePaint());
Car blackCar = new Car(new BlackPaint());
Motorbike whiteBike = new Motorbike(new WhitePaint());
Motorbike blackBike = new Motorbike(new WhitePaint());
}
}
public static void main(String[] args) {
Car whiteCar = new Car(new WhitePaint());
Car blackCar = new Car(new BlackPaint());
Motorbike whiteBike = new Motorbike(new WhitePaint());
Motorbike blackBike = new Motorbike(new WhitePaint());
}
}