A Complete Guide to Structural Design Patterns in Java: The Bridge Pattern

Varsha Das
Javarevisited
Published in
4 min readNov 9, 2022

What is a design pattern?

A software design pattern is a general, reusable solution to a commonly occurring problem within a given context in software design.

Why should I learn patterns?

Makes life simpler by not reinventing the wheel

  1. Toolbox of time-tested solutions to common problems in software design.
  2. Defines a common language between the team and organization to solve emerging issues related to technological advancements.
  3. Start understanding patterns in libraries and languages.

Classification of patterns

Creational

Structural

Behavioral

We have already covered Creational patterns — Check here

There are 7 types of Structural Design patterns:

  1. Adapter
  2. Bridge
  3. Facade
  4. Decorator
  5. Flyweight
  6. Composite
  7. Proxy

In this article, we will focus in detail on the Bridge design pattern.

Usage:

Decouple an abstraction from its implementation so that the two can vary independently

In simpler words, this pattern helps to simplify inheritance structures.

Bridge pattern involves an interface that acts as a bridge, comes under structural pattern as this pattern decouples the implementation class and abstract class by providing a bridge structure between them.

Existing problem:

Ever seen an application that uses lots of inheritance?

It starts off as a nice, simple tree with a parent and a few children.

Over time, you find that you need to add another level, and after some time, you have a huge inheritance tree that looks something like this.

A classic example of where the bridge pattern can be used is in a graphical user interface. You have an interface called Shape, and underneath you some classes such as hexagon, triangle and square.

Then you might decide that you want to have different color shapes, so the next logical step is to extend the inheritance tree to have a blue hexagon, a red triangle, a green square, and a red hexagon and so on.

Every time you want to add a color, you have to make two new classes.

This eventually results in larger, duplicated, and difficult-to-understand code.

How can the Bridge pattern help?

Separates out your hierarchy and makes your code more flexible.

The implementation of the bridge design pattern follows the notion to prefer Composition over inheritance.

Going by the above example, the bridge pattern enables instantiating a blue square object, for example, without needing to write a blue square class as a whole.

Instead, we can use the characteristics of both the ‘independent’ square class and the blue shape class.

In this way, the bridge pattern can help to write more maintainable code, it decouples the concrete implementation from the interface and gives more flexibility.

Code:

Let’s say we need to refactor an app for drawing different types of buttons on a canvas.

There is an abstract class called Button, and underneath that, there are three more abstract classes called the checkbox button, dropdown button, and radio box button. Under this level are the concrete classes.

Each type of button has a small, medium, and large version. So there are two hierarchies being mixed here, the type of button and the size of the button.

Expected output:

A quick glimpse of how the classes look in the IDE:

Quite a few classes, huh?

The more types of buttons we add, the more complex this workflow will be.

Lets’s separate the hierarchies using the Bridge pattern

There’s an interface that we create called ButtonSize, which has one method called getSize.

Next, we will have three classes that implement ButtonSize called LargeButtonSize, MediumButtonSize, and SmallButtonSize.

They each override the getSize() method and print out the size of the button.

Now in each of the different types of button, DropdownButton, CheckboxButton, and RadioButton, in the constructor of each of them, we are passing in a button-size object.

Finally, in the Canvas class, instead of having a separate class for each size and type of button, we pass in a new button-size object, which specifies the size of the button we want to have.

Output:

So now we have two separate hierarchies, one for the button type, and one for the button size, without having to create lots of new classes.

If you liked this article, please click the “clap” button 👏 a few times.

Gives me enough motivation to put out more content like this. Please share it with a friend who you think this article might help.

Follow me Varsha Das to receive my weekly articles.

Connect with me — Varsha Das | LinkedIn

Follow my Youtube channel — Code With Ease — By Varsha, where we discuss Data Structures & Algorithms.

Thanks for reading.

Happy learning! 😁

--

--

Varsha Das
Javarevisited

"Senior Software Engineer @Fintech | Digital Creator @Youtube | Thrive on daily excellence | ❤️ complexity -> clarity | Devoted to health and continuous growth