Structural Handle/Body

Bridge

Bridge is a structural pattern that splits a class along two independent axes of change - what it does and how it does it - connecting the two halves through composition instead of inheritance.

Complexity
Popularity

Problem

A remote-control class hierarchy starts with a base `RemoteControl` and a `AdvancedRemote` subclass that adds extras like mute. Then the team needs to support multiple device types - TVs, radios, and more. Following the same inheritance approach means creating `TVBasicRemote`, `TVAdvancedRemote`, `RadioBasicRemote`, `RadioAdvancedRemote`, and so on.

Each new device type or new remote variant multiplies the existing subclasses instead of adding one class. The hierarchy is really modeling two separate concerns - the remote's control logic and the device it operates - but inheritance forces them into a single chain, so they can't vary independently.

Solution

Pull one of the two concerns out into its own hierarchy, and connect it to the original hierarchy through a held reference rather than inheritance. In the remote-control example, devices (`TV`, `Radio`) become a separate hierarchy behind a common `Device` interface. The `RemoteControl` class stops assuming a specific device and instead holds a device object, forwarding the actual power and volume operations to it.

That held reference is the bridge: remote variants and device types can now each grow their own hierarchy, and any remote - basic or advanced - can be paired with any device at runtime, without a combinatorial explosion of subclasses.

When to Use

  • A class is growing subclasses along two unrelated dimensions at once - for example, message priority and delivery channel, or shape type and rendering backend.
  • You expect to add new variants on either side over time and want that growth to stay linear, not multiplicative.
  • You need to swap the underlying implementation at runtime - for instance, pointing the same high-level code at a live service in production and a stub in tests.

Real-World Examples

  • **JDBC drivers** - application code calls the same `Connection`/`Statement` abstraction while MySQL, PostgreSQL, or SQLite each supply their own driver implementation underneath.
  • **SLF4J logging facade** - code logs through one abstract API regardless of whether Logback, Log4j2, or java.util.logging ends up handling the actual output.
  • **Cross-platform rendering in game engines** - a `Renderer` abstraction stays the same while separate implementations target DirectX, Vulkan, or Metal depending on the platform.