Structural Design Patterns provide different ways to create a class structure, for example using inheritance and composition to create a large object from small objects. Following design patterns come under this category.
Bridge pattern is about preferring composition over inheritance. Implementation details are pushed from a hierarchy to another object with a separate hierarchy.
When we have interface hierarchies in both interfaces as well as implementations, then Bridge design pattern is used to decouple the interfaces from implementation and hiding the implementation details from the client programs.
According to GoF bridge design pattern is:
Decouple an abstraction from its implementation so that the two can vary independently.
This pattern involves an interface which acts as a bridge which makes the functionality of concrete classes independent from interface implementer classes. Both types of classes can be altered structurally without affecting each other.
In the bridge pattern, we separate an abstraction and its implementation and develop separate inheritance structures for both the abstraction and the implementer. The Bridge pattern’s intent is to decouple an abstraction from its implementation so that the two can vary independently. It puts the abstraction and implementation into two different class hierarchies so that both can be extend independently.
Before applying Bridge design pattern:
After applying Bridge design pattern:
The figure below shows a UML class diagram for the Bridge pattern:
The participants classes in the bridge pattern are:
Summary of Bridge design pattern:
We are demonstrating use of Bridge pattern via following example in which a circle can be drawn in different colors using same abstract class method but different bridge implementer classes.
Java
Following example includes following elements:
Shape
(Abstraction)Rectangle
(RefinedAbstraction)Circle
(RefinedAbstraction)Color
(Implementor)RedColor
(ConcreteImplementor)BlueColor
(ConcreteImplementor)We have two inheritance hierarchies here i.e. Shape
and Color
. Now with help of Bridge design pattern both can vary independently.
This is our abstraction class.
abstract class Shape { Color color; Shape(Color color) { this.color = color; } abstract public void colorIt(); }
public class Rectangle extends Shape { Rectangle(Color color) { super(color); } public void colorIt() { System.out.print("Rectangle filled with "); color.fillColor(); } }
public class Circle extends Shape{ Circle(Color color) { super(color); } public void colorIt() { System.out.print("Circle filled with "); color.fillColor(); } }
This is our implementor class.
public interface Color { public void fillColor(); }
public class RedColor implements Color { public void fillColor() { System.out.println("red color"); } }
public class BlueColor implements Color { public void fillColor() { System.out.println("blue color"); } }
public class BridgeDesignPatternMain { public static void main(String[] args) { Shape s1 = new Rectangle(new RedColor()); s1.colorIt(); Shape s2 = new Circle(new BlueColor()); s2.colorIt(); } }
Python 3
import abc class Color(metaclass=abc.ABCMeta): @abc.abstractmethod def fill_color(self): pass class Shape(metaclass=abc.ABCMeta): def __init__(self, color): self.color = color @abc.abstractmethod def color_it(self): pass class Rectangle(Shape): def __init__(self, color): super(Rectangle, self).__init__(color) def color_it(self): print("Rectangle filled with ", end="") self.color.fill_color() class Circle(Shape): def __init__(self, color): super(Circle, self).__init__(color) def color_it(self): print("Circle filled with ", end="") self.color.fill_color() class RedColor(Color): def fill_color(self): print("red color") class BlueColor(Color): def fill_color(self): print("blue color") if __name__ == '__main__': s1 = Rectangle(RedColor()) s1.color_it() s2 = Circle(BlueColor()) s2.color_it()