JavaRush /Java Blog /Random EN /Bridge Design Pattern

Bridge Design Pattern

Published in the Random EN group
Hello! We continue to understand a broad and very useful topic - design patterns. Today we'll talk about Bridge. Like other patterns, Bridge serves to solve common problems that a developer faces when designing software architecture. Let's study its features today and find out how to use it.

What is the Bridge pattern?

The Bridge pattern is a structural design pattern. That is, its main task is to create a complete structure of classes and objects. Bridge solves this problem by separating one or more classes into separate hierarchies - abstraction and implementation . A change in functionality in one hierarchy does not entail changes in another. Everything seems clear, but in fact this definition sounds very broad and does not answer the main question: “What is the Bridge pattern?” I think this will be easier for you to figure out in practice. Let's immediately model a classic example for the Bridge pattern. We have an abstract class Shapethat generally describes a geometric figure:
  • Shape.java

    public abstract class Shape {
       public abstract void draw();
    }

    When we decide to add triangle and rectangle shapes, we will inherit from the class Shape:

  • Rectangle.java:

    public class Rectangle extends Shape {
       @Override
       public void draw() {
           System.out.println("Drawing rectangle");
       }
    }
  • Triangle.java:

    public class Triangle extends Shape {
       @Override
       public void draw() {
           System.out.println("Drawing triangle");
       }
    }
Everything looks simple until we introduce the concept of “color”. That is, each figure will have its own color, on which the functionality of the method will depend draw(). To have different implementations of the method draw(), we need to create a class for each shape corresponding to a color. If there are three colors, then there are six classes: TriangleBlack, TriangleGreen, TriangleRed, RectangleBlack, RectangleGreenand RectangleRed. Six classes is not that big of a deal. But! If we need to add a new shape or color, the number of classes will grow exponentially. How to get out of this situation? Storing colors in a field and trying options through conditionals is not the best solution. A good solution is to display color in a separate interface . No sooner said than done: let's create an interface Colorand three of its implementations - BlackColor, GreenColorand RedColor:
  • Color.java:

    public interface Color {
       void fillColor();
    }
  • BlackColor.java:

    public class BlackColor implements Color {
       @Override
       public void fillColor() {
           System.out.println("Filling in black color");
       }
    }
  • GreenColor.java

    public class GreenColor implements Color {
       @Override
       public void fillColor() {
           System.out.println("Filling in green color");
       }
    }
  • RedColor.java

    public class RedColor implements Color {
       @Override
       public void fillColor() {
           System.out.println("Filling in red color");
       }
    }

    Now let's add a type field Colorto the class Shape- we will receive its value in the constructor.

  • Shape.java:

    public abstract class Shape {
       protected Color color;
    
       public Shape(Color color) {
           this.color = color;
       }
    
       public abstract void draw();
    }

    colorWe will use the variable in implementations Shape. This means that shapes can now use the functionality of the interface Color.

  • Rectangle.java

    public class Rectangle extends Shape {
    
       public Rectangle(Color color) {
           super(color);
       }
    
       @Override
       public void draw() {
           System.out.println("Drawing rectangle");
           color.fillColor();
       }
    }
Here you go! Now we can produce different colors and geometric shapes even ad infinitum, increasing the number of classes in arithmetic progression. The field Color coloris a bridge that interconnects two separate class hierarchies.

Bridge device: what is abstraction and implementation

Let's take a look at the class diagram that describes the Bridge pattern: Introduction to the Bridge design pattern - 2Here you can see two independent structures that can be modified without affecting each other's functionality. In our case it is:
  • Abstraction - class Shape;
  • RefinedAbstraction - classes Triangle, Rectangle;
  • Implementor - interface Color;
  • ConcreteImplementor - classes BlackColor, GreenColorand RedColor.
The class Shaperepresents an Abstraction - a mechanism for controlling the coloring of shapes in different colors, which delegates the Implementation to the interface Color. Classes Triangleare Rectanglereal objects that use the mechanism offered by the class Shape. BlackColor, GreenColorand RedColor- specific implementations in the Implementation branch. They are often called a platform.

Where is the Bridge pattern used?

A huge advantage of using this pattern is that you can make changes to the functionality of classes in one branch without breaking the logic of another. This approach also helps to reduce the coupling of program classes. The main condition for using patterns is to “follow the instructions”: don’t stick them anywhere! Actually, let's figure out in what cases you definitely need to use Bridge:
  1. If it is necessary to expand the number of entities in two directions (geometric shapes, colors).

  2. If you want to divide a large class that does not meet the Single responsibility principle into smaller classes with narrow-profile functionality.

  3. If there is a possible need to make changes to the logic of the operation of certain entities while the program is running.

  4. If necessary, hide the implementation from class (library) clients.

When using a pattern each time, you need to remember that it adds additional entities to the code - it is not entirely logical to use it in a project where there is only one geometric figure and one or two possible colors.

Pros and cons of the pattern

Like other patterns, the Bridge has both advantages and disadvantages. Benefits of Bridge:
  1. Improves code scalability - you can add functionality without fear of breaking something in another part of the program.
  2. Reduces the number of subclasses - works when it is necessary to expand the number of entities in two directions (for example, the number of shapes and the number of colors).
  3. Makes it possible to work separately on two independent branches of Abstraction and Implementation - this can be done by two different developers without delving into the details of each other’s code.
  4. Reducing the coupling of classes - the only place where two classes are connected is the bridge (field Color color).
Disadvantages of Bridge:
  1. Depending on the specific situation and the structure of the project as a whole, there may be a negative impact on program productivity (for example, if more objects need to be initialized).
  2. Complicates code readability due to the need to navigate between classes.

Difference from the Strategy pattern

The Bridge pattern is often confused with another design pattern, Strategy. They both use composition (in the shapes and colors example we used aggregation, but the Bridge pattern can also use composition) by delegating the work to other objects. But there is a difference between them, and it is huge. The Strategy pattern is a behavioral pattern: it solves completely different problems. Strategy allows for interchangeability of algorithms, while Bridge separates abstraction from implementation to allow choice between different implementations. That is, Bridge, unlike Strategy, applies to entire constructs or hierarchical structures. The Bridge pattern can be a good weapon in a developer’s arsenal; the main thing is to find those situations where it is worth using it, or use some other pattern. If you are not yet familiar with other templates, read these materials:
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION