Bridge Design Pattern

Name: Bridge Design Pattern

Type: Structural Design Pattern

Purpose: Decouple abstraction from implementation
                (In other words using composite over inheritance)

Sample Problem and Solution:
Assume that you are required to create some Shapes with two different patterns. Some sample shapes are SolidColorCircle, GradientCircle, SolidColorSquare and GradientSquare. A possible design is provided below.
public interface Shape {
    public void draw();
}
public abstract class Circle implements Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public void draw() {
        System.out.println("Create a circle with radius: " + radius);
    }
}
public class SolidColorCircle extends Circle {
    private String color;

    public SolidColorCircle(double radius, String color) {
        super(radius);
        this.color = color;
    }

    @Override
    public void draw() {
        super.draw();
        System.out.println("Fill with: " + color);
    }
}
public class GradientCircle extends Circle {
    private String colorX;
    private String colorY;

    public SolidColorCircle(double radius, String colorX, String colorY) {
        super(radius);
        this.colorX = colorX;
        this.colorY = colorY;
    }

    @Override
    public void draw() {
        super.draw();
        System.out.println("Fill with: " + colorX + " & " + colorY);
    }
}
Square, SolidColorSquare and GradientSquare are provided in GitHub.

A sample client, using these classes:
public class Main {
    public static void main(String[] args) {
        Shape circle = new SolidColorCircle(7.0, "RED");
        Shape square = new GradientSquare(10, "BLUE", "GREEN");
        circle.draw();
        square.draw();
    }
}
In this design, we have an abstract class Shape which is the super parent class of the hierarchy and then there can be any other abstract classes like Circle, Square, etc. Each and every sub classes need to have two more sub classes to define the background. The same code for SolidColor and Gradient attributes is duplicated in the sub classes.

Even though inheritance helps to avoid code duplication, a deep inheritance hierarchy causes to tight coupling between super class and its implementations (sub classes). There are even more disadvantages in inheritance and it will be discussed in another article.

Bridge design pattern is the solution for this problem which enforces the composition over inheritance rule. The new design using Bridge pattern is provided below.
public interface Shape {
    public void draw();
}
public interface Background {
    public void fill();
}
public class SolidColor implements Background {
    private String color;

    public SolidColor(String color) {
        this.color = color;
    }

    @Override
    public void fill() {
        System.out.println("Fill with: " + color);
    }
}
public class Gradient implements Background {
    private String colorX;
    private String colorY;

    public Gradient(String colorX, String colorY) {
        this.colorX = colorX;
        this.colorY = colorY;
    }

    @Override
    public void fill() {
        System.out.println("Fill with: " + colorX + " & " + colorY);
    }
}
public class Circle implements Shape {
    private double radius;
    private Background background;

    public Circle(double radius, Background background) {
        this.radius = radius;
        this.background = background;
    }

    @Override
    public void draw() {
        System.out.println("Create a circle with radius: " + radius);
        background.fill();
    }
}
public class Square implements Shape {
    private double width;
    private Background background;

    public Square(double width, Background background) {
        this.width = width;
        this.background = background;
    }

    @Override
    public void draw() {
        System.out.println("Create a square with width: " + width);
        background.fill();
    }
}

The client can create these shapes by providing the desired background.
public class Main {
    public static void main(String[] args) {
        Shape circle = new Circle(7.0, new SolidColor("RED"));
        Shape square = new Square(10.0, new Gradient("BLUE", "GREEN"));
        circle.draw();
        square.draw();
    }
}
In this design the inheritance is removed and the background attribute is added through composition. According to the current design one class is enough to create a new Shape, while three classes were needed for the previous design. As you can see, the tight coupling between background color and shape is removed using Bridge design pattern, so the color of shape can vary independently. Whenever you smell a deep inheritance hierarchy which causes to tight coupling among super class(or interface) and sub classes, apply the Bridge design pattern to avoid the tight coupling.

Famous application of Bridge design pattern:

Quick recipe:
  1. Decouple the shared features into a separate class hierarchy.
  2. Add the extracted feature using composition
Find the source codes at Git Hub.
Previous
Next Post »

Contact Form

Name

Email *

Message *