Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesThe 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.
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.
Rank #2
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:
- 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.
Rank #4
| 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.
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.
Quick Recap
Best Value
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.

