Bridge Design Pattern in Java

Bridge Design Pattern in Java with Examples

In this article, I am going to discuss Bridge Design Patterns in Java with Examples. Please read our previous article where we discussed Adapter Design Patterns in Java with Examples. The Bridge Design Pattern falls under the category of the Structural Design Pattern. In this article, we will explore the fundamental principles, advantages, and potential disadvantages of the Bridge design pattern, emphasizing its significance in promoting loose coupling, facilitating platform independence, and enabling future enhancements.

What is Bridge Design Pattern?

In software development, it is crucial to design systems that can accommodate variations in both functionality and implementation. The Bridge design pattern provides a solution by decoupling an abstraction from its implementation, allowing them to vary independently. By encapsulating the abstraction and implementation in separate hierarchies, the pattern promotes flexibility, extensibility, and maintainability.

According to GOF definitions, the Bridge Design Pattern Decouples an abstraction from its implementation so that the two can vary independently.

In the Bridge Design Pattern, there are 2 parts. The first part is the Abstraction and the second part is the Implementation. The Bridge Design Pattern allows both Abstraction and Implementation to be developed independently and the client code can only access the Abstraction part without being concerned about the Implementation part.

The Bridge Design Pattern separates the Abstraction hierarchy and the Implementation hierarchy into two different layers so that change in one Hierarchy will not affect the development or functionality of another Hierarchy.

The Bridge design involves the following components:

  • Abstraction: Defines the high-level interface or abstraction that clients interact with. It maintains a reference to an object of the implementation hierarchy.
  • Implementation: Represents the low-level implementation or concrete implementation classes. It provides specific implementations of the operations defined by the abstraction.
  • Refinement: Extends the abstraction hierarchy independently from the implementation hierarchy, enabling variations and extensions in both hierarchies.
  • Client: Utilizes the abstraction to interact with the system without being exposed to the implementation details.
Real-Time Example of Bridge Design Pattern in Java:

Please have a look at the following image for a better understanding of the Bridge Design Pattern. On the left-hand side, you can see the Abstraction. Suppose, you want to turn on the TV or turn off the TV, then what you can do here is, you can use the Remote Control to turn On/Off the TV. The Implementation will be done by the original TV implementer. So, in this case, Samsung TV or Sony TV will implement the turn On or turn Off functionality. So, the abstraction will use one of the implementers to turn on or turn off the TV.

Real-Time Example of Bridge Design Pattern in Java

Suppose, later you want to add a new implementation then you can do this in the Implementation Layer. For example, you can add new TV (for example Panasonic TV) in the Implementation Layer which will not affect the Abstraction Layer. You can also add a new Panasonic TV Remote Control in the Abstraction Layer without affecting the Implementation Layer. So, this is one of the best examples of the Bridge Design Pattern.

Example to Understand Bridge Design Pattern in Java

The bridge pattern can be used to design a system to manage the students of a particular school. This allows us to make the code more modular. It also makes it easier to add/update/delete students. The UML Diagram of this example is given below using Bridge Design Pattern.

Example to Understand Bridge Design Pattern in Java

Implementing Bridge Design Pattern in Java

Step 1: Create a new directory to store all the class files of this project.

Step 2: Open VS Code and create a new project, called bridge.

Step 3: In the project, create a new file called Student.java. Add the following code to the file:

Implementing Bridge Design Pattern in Java

Step 4: In the project, create a new file called SchoolStudents.java.

Step 5: Import the following packages into SchoolStudents.java:

Bridge Design Pattern in Java

Step 6: Define the following fields in the class:

Bridge Design Pattern in Java with Examples

Step 7: Add a constructor that initializes the list of students:

What is a Bridge Design Pattern?

Step 8: Implement the next() and prev() functions. These functions were defined in the Student interface. These will be implemented in this class:

UML Diagram of Bridge Design Pattern in Java

Step 9: Implement the other functions (which were defined in the interface) as well:

Example to Understand Bridge Design Pattern in Java

Step 10: In the project, create a new file called StudentManager.java. Add the following code to the file:

Implementing Bridge Design Pattern in Java

Step 11: In the project, create a new file called StudentFormat.java. Add the following code to the file:

Bridge Pattern in Java

Step 12: In the project, create a new file called BridgePatternDemo.java. This file will contain the main() function. Add the following code to the file:

Bridge Pattern in Java with Examples

Step 13: Compile and execute the application. Ensure compilation is successful. Verify that the program works as expected.

What is a Bridge Pattern?

Congratulations! You now know how to implement bridge patterns!

UML Diagram of Bridge Design Pattern:

Now, let us see the Bridge Design Pattern UML Diagram Components with our Example so that you can easily understand the UML Diagram.

UML Diagram of Bridge Design Pattern

The classes can be described as follows:

  1. ObjectFormat: This class is used to format the object.
  2. ObjectManager: This class is used to handle the object operations, such as add, delete, update, etc.
  3. Object: This interface defines the functions that must be supported by the object. The implementation of these function need to be defined in another class (which implements this class)
  4. TypeOfObject: This class implements the Object interface and all its functions.
The Complete Example Code of Bridge Design Pattern using Java
BridgePatternDemo.java
public class BridgePatternDemo
{
    public static void main(String[] args)
    {
        StudentFormat studentFormat = new StudentFormat("Students of School XYZ");
        studentFormat.s = new SchoolStudents();

        System.out.println("Default list of students: ");
        studentFormat.displayAll();
        System.out.println();

        System.out.println("After adding new students: ");
        studentFormat.newStudent("Student X");
        studentFormat.newStudent("Student Y");
        studentFormat.newStudent("Student Z");
        studentFormat.displayAll();
        System.out.println();

        System.out.println("After deleting a student: ");
        studentFormat.delete("Student C");
        studentFormat.displayAll();
        System.out.println();
    }
}
SchoolStudents.java
import java.util.ArrayList;
import java.util.List;

public class SchoolStudents implements Student
{
    private List<String> students = new ArrayList<String>();
    private int curr = 0;

    public SchoolStudents()
    {
        students.add("Student A");
        students.add("Student B");
        students.add("Student C");
        students.add("Student D");
        students.add("Student E");
        students.add("Student F");
    }

    @Override
    public void next()
    {
        if (curr <= students.size() + 1)
            curr++;

        System.out.println(curr);
    }

    @Override
    public void prev()
    {
        if (curr > 0)
            curr++;

        System.out.println(curr);
    }

    @Override
    public void newStudent(String s)
    {
        students.add(s);
    }

    @Override
    public void delete(String s)
    {
        students.remove(s);
    }

    @Override
    public void display()
    {
        System.out.println(students.get(curr));
    }

    @Override
    public void displayAll()
    {
        for (String s : students)
            System.out.println(s);
    }
}
Student.java
public interface Student
{
    public void next();
    public void prev();
    public void newStudent(String s);
    public void delete(String s);
    public void display();
    public void displayAll();
}
StudentFormat.java
public class StudentFormat extends StudentManager
{
    public StudentFormat(String catalogue)  {super(catalogue);}
    public void displayAll()                {super.displayAll();}
}
StudentManager.java
public class StudentManager
{
    protected Student s;
    public String catalogue;
    
    public StudentManager (String catalogue)    {this.catalogue = catalogue;}
    public void next()                          {s.next();}
    public void prev()                          {s.prev();}
    public void newStudent(String newStudent)   {s.newStudent(newStudent);}
    public void delete(String deleteStudent)    {s.delete(deleteStudent);}
    public void display()                       {s.display();}
    public void displayAll()                    {s.displayAll();}
}
Advantages of using Bridge Design Pattern in Java:
  • Loose Coupling: The Bridge pattern promotes loose coupling between the abstraction and its implementation. By encapsulating the implementation details behind an abstraction, changes in either the abstraction or implementation hierarchy can be made independently without affecting each other, reducing the overall impact of modifications.
  • Platform Independence: The Bridge pattern facilitates platform independence by separating the abstraction from its implementation. This allows the system to support different platforms or technologies without directly coupling to them. It enables abstraction to be used with multiple implementations, promoting interoperability and enhancing system flexibility.
  • Extensibility: The Bridge pattern supports extensibility by allowing the independent evolution of the abstraction and implementation hierarchies. New abstractions or implementations can be added without modifying existing code, making it easier to introduce new features or variations in the system.
  • Improved Maintainability: Decoupling the abstraction from its implementation simplifies system maintenance. Changes in either hierarchy can be localized and isolated, reducing the ripple effect on other parts of the codebase. This promotes better code organization and easier maintenance, especially in large-scale systems.
  • Run-time Flexibility: The Bridge pattern provides run-time flexibility by allowing the interchangeability of different implementations at runtime. Clients can switch implementations dynamically, making it possible to adapt the behavior of the system based on changing requirements or runtime conditions.
Disadvantages of using Bridge Design Pattern in Java:
  • Increased Complexity: Implementing the Bridge pattern introduces additional complexity to the codebase. The separation of abstraction and implementation hierarchies can lead to a more intricate system structure, which may require additional effort to understand and maintain.
  • Design Overhead: The Bridge pattern requires careful design and identification of the abstraction and implementation hierarchies. This upfront design effort is essential to ensure proper separation and flexibility, but it can increase the initial design overhead of the system.
  • Potential Overuse: Overusing the Bridge pattern can lead to unnecessary abstraction and complexity in the codebase. It is crucial to apply the pattern judiciously and only when there is a genuine need for abstraction and independent variation between abstraction and implementation.
  • Increased Development Time: Developing and maintaining multiple hierarchies (abstraction and implementation) may require more time and effort compared to a simpler, monolithic design. This additional development time should be weighed against the benefits gained from the increased flexibility and maintainability.
  • Coordination Challenges: When changes are made to the abstraction and implementation hierarchies, coordination between the two can become challenging. Ensuring consistency and compatibility between the two hierarchies may require additional effort and careful consideration during the design and implementation phases.

In the next article, I am going to discuss Composite Design Patterns in Java with Examples. Here, in this article, I try to explain Bridge Design Pattern in Java with Examples. I hope you understood the need for and use of Bridge Design Patterns in Java.

Leave a Reply

Your email address will not be published. Required fields are marked *