Design Patterns Bridge

The Bridge pattern splits one large class into two separate hierarchies: an abstraction and an implementation. A reference links them, and each side grows independently. Developers avoid a flood of combined subclasses.

The Real-World Analogy

Consider remote controls and televisions. A basic remote and an advanced remote both work with any brand of TV. Nobody builds a separate remote for every remote-and-TV pair. The remote holds a link to a TV, and the two sides evolve on their own.

Problem Without Bridge

Shape
 ├── RedCircle
 ├── BlueCircle
 ├── RedSquare
 ├── BlueSquare
 ├── RedTriangle
 └── BlueTriangle

3 shapes × 2 colors = 6 classes.   Add green → 9 classes.   Add a shape → 12 classes.

The class count multiplies with every new option. Maintenance becomes painful quickly.

Solution With Bridge

 Abstraction side                 Implementation side
┌──────────────┐   has-a        ┌──────────────┐
│ Shape        │ ─────────────▶ │ Color        │
└──────▲───────┘                └──────▲───────┘
   ┌───┴────┐                      ┌───┴────┐
 Circle   Square                  Red     Blue

3 shapes + 2 colors = 5 classes.   Add green → 6 classes.

Addition replaces multiplication. Each new color or shape costs exactly one class.

Structure

┌────────────────────────┐       ┌─────────────────────────┐
│ Abstraction            │       │ «interface»             │
│ - impl: Implementor    │──────▶│ Implementor             │
│ + operation()          │       │ + operationImpl()       │
└──────────▲─────────────┘       └────────────▲────────────┘
           │                                  │
┌──────────┴─────────────┐       ┌────────────┴────────────┐
│ RefinedAbstraction     │       │ ConcreteImplementor     │
└────────────────────────┘       └─────────────────────────┘

Roles

  • Abstraction: the high-level control layer that holds a reference.
  • Implementor: the interface for low-level work.
  • Refined Abstraction: a variant of the control layer.
  • Concrete Implementor: one real version of the low-level work.

Code Example

interface Color { String fill(); }

class Red  implements Color { public String fill() { return "red"; } }
class Blue implements Color { public String fill() { return "blue"; } }

abstract class Shape {
    protected Color color;                  // the bridge
    Shape(Color color) { this.color = color; }
    abstract void draw();
}

class Circle extends Shape {
    Circle(Color color) { super(color); }
    void draw() { print("Circle filled with " + color.fill()); }
}

class Square extends Shape {
    Square(Color color) { super(color); }
    void draw() { print("Square filled with " + color.fill()); }
}

new Circle(new Red()).draw();    // Circle filled with red
new Square(new Blue()).draw();   // Square filled with blue

Real Projects Using Bridge

ScenarioAbstractionImplementation
Notification appAlert types: urgent, normalChannels: email, SMS, push
Graphics toolShapesRendering engines
Device appsRemote typesDevice brands

Bridge Versus Adapter

Adapter fixes a mismatch after two classes already exist. Bridge plans the split from the start. Designers pick Bridge during early planning and Adapter during integration.

Advantages and Disadvantages

AdvantagesDisadvantages
Two hierarchies grow independentlyMore upfront design effort
Fewer classes overallExtra indirection for small programs
Runtime swapping of implementationsBeginners need time to see the split

Step-by-Step Walkthrough

Follow the shape example. The client picks a Red color object and a Circle shape, and joins them through the Circle constructor. Inside the Circle, a protected field stores the color. Calling draw() asks the color for its fill name and prints the combined result.

A new color named Green needs one small class that implements Color. Every existing shape accepts it instantly, because shapes know only the Color interface. A new shape named Triangle needs one class that extends Shape. Every existing color works with it immediately.

Spotting the Need for Bridge

Look at class names in a project. Names that join two ideas, such as RedCircle, BlueSquare, or SmsUrgentAlert, signal two dimensions mixed in one hierarchy. Split the dimensions, and the multiplying names vanish.

Plain-Words Summary

Think of Bridge as a plug-and-socket design for classes. Each side defines a clear connector, and any matching part snaps in. Teams that adopt the habit stop fearing new requirements, because a new option means one new class instead of a tangle of edits across the hierarchy. Beginners often grasp the idea fastest by drawing two columns of boxes and linking them with a single arrow.

Key Takeaways

  • Bridge separates "what" from "how" using composition.
  • It prevents the class explosion from combining two changing dimensions.
  • Implementations swap at runtime through the reference.
  • Plan Bridge early, while Adapter patches mismatches later.