Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The Bridge pattern separates a high-level abstraction from the implementation it uses. In Java, the abstraction holds an implementation interface and delegates work to it, letting both sides grow independently without a subclass for every combination.

What is the Bridge pattern?

Bridge is a structural design pattern. Its classic definition is to “decouple an abstraction from its implementation so that the two can vary independently,” a formulation attributed to the Gang of Four and quoted by InformIT.

In practical terms, use composition: an abstraction stores a reference to an implementation object and delegates implementation-specific work through that object’s contract. This is useful when a design has two independent variation axes. Instead of building one inheritance tree for every possible combination, each axis gets its own hierarchy.

How the pattern’s participants fit together

  • Client: works with the abstraction’s public API.
  • Abstraction: defines the high-level API and holds a reference to an Implementor.
  • Refined Abstraction: extends the abstraction with domain-specific operations.
  • Implementor: defines the lower-level implementation contract.
  • Concrete Implementor: supplies a particular implementation, such as a platform- or behavior-specific version.

The abstraction depends on the Implementor interface rather than a specific implementation class. That means a client can choose a concrete implementation when it constructs the abstraction, while the abstraction’s high-level API remains the same.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A simple Bridge pattern example in Java

This example separates shapes from colors. A shape delegates its color-specific behavior to a Color object.

interface Color {
    String fill();
}

final class Red implements Color {
    public String fill() {
        return "Color is Red";
    }
}

abstract class Shape {
    protected final Color color;

    protected Shape(Color color) {
        this.color = color;
    }

    abstract String draw();
}

final class Square extends Shape {
    Square(Color color) {
        super(color);
    }

    String draw() {
        return "Square drawn. " + color.fill();
    }
}

class Demo {
    public static void main(String[] args) {
        Shape square = new Square(new Red());
        System.out.println(square.draw());
        // Square drawn. Color is Red
    }
}

Where the bridge is

Shape is the abstraction, and Square is a refined abstraction. Color is the Implementor interface, while Red is a Concrete Implementor. Passing a Color into the shape constructor creates the bridge: Shape uses the color contract without depending on the Red class.

You can add a new shape subclass or a new color implementation independently. For example, a Circle can use any implementation of Color; a new color does not require a new shape class for every shape. In a real application, keep the implementation contract focused on the behavior the abstraction needs.

When to use Bridge

Bridge is a good fit when both the abstraction and its implementation need to vary, or when the number of combinations is making inheritance unwieldy. Consider it when:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • New abstraction variants and implementation variants should be added independently.
  • The implementation can be selected at runtime, such as when creating an object for a particular platform.
  • Changes to an implementation should not force clients to depend on or recompile against its details.
  • A hierarchy is becoming a grid of combinations, with a subclass for each pairing.

Common conceptual examples include a GUI abstraction over operating-system window systems, a generic database interface over vendor drivers, and device-independent code over device drivers. The pattern is worthwhile when that separation solves a real change or extension problem; for a single stable implementation, the extra layer may not pay for itself.

Bridge versus Adapter

Bridge and Adapter can both use composition, so their structures may look similar. Their intent is different: Bridge is designed into a system so two dimensions can vary independently; Adapter is generally introduced afterward to make an existing incompatible interface work with the interface a client expects.

Pattern Typical purpose When the design is introduced
Bridge Keep an abstraction and its implementation independently extensible. As part of the design, before the independent variation becomes a problem.
Adapter Translate between incompatible interfaces so existing components can work together. Usually after the components or interfaces already exist.

Ask whether you are planning two independent axes of change (Bridge) or adapting an existing interface to a required one (Adapter). The use of composition alone does not determine which pattern applies.

Benefits and trade-offs

  • Independent extension: abstraction variants and implementation variants can evolve separately.
  • Fewer combination subclasses: composition avoids a class for every pairing of the two hierarchies.
  • Encapsulation: clients can use the high-level API without knowing implementation details.
  • More structure: the extra interfaces, classes, and delegation add concepts readers must follow.
  • Indirection: each delegated operation passes through another object. Java Design Patterns describes the runtime penalty as generally negligible, but does not provide a benchmark figure.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Runnable study material

For a fuller Java project example, the design-patterns-with-java repository’s Bridge module is located at design-patterns/structural/bridge. The project uses Maven modules and JUnit 5 tests, documents JDK 17 or later, and its CI also builds on JDK 21.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.