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.