0 XP · 0 scenes

Bridge

Split a thing into two parts that can vary on their own
The problem

You have two kinds of remote and two kinds of device, so you write BasicTvRemote, BasicRadioRemote, AdvancedTvRemote and AdvancedRadioRemote.

The idea

Keep two small hierarchies and join them with a reference.

Reach for it when

A class varies in two independent directions

1

The picture from life

A remote control and a TV are different things. Any remote (basic, advanced) can work with any device (TV, radio) because they meet at a small standard: power, volume. You can buy a better remote or a new TV separately. The standard is the bridge.

2

The problem

What goes wrong when you do not use it.

You have two kinds of remote and two kinds of device, so you write BasicTvRemote, BasicRadioRemote, AdvancedTvRemote and AdvancedRadioRemote. Add a third device and you write two more classes; add a third remote and you write three more. The class count multiplies.

✗ Before
BasicTvRemoteBasicRadioRemoteAdvancedTvRemoteAdvancedRadioRemote+ Speaker = 2 more+ VoiceRemote = 3 more...
Two ways to vary (remote type × device) multiply into many classes. A new device doubles the work.
Reach for it when
  • A class varies in two independent directions
  • You want to swap the implementation at run time
  • Subclassing would create a grid of combinations
3

The idea

How the pattern fixes it.

Keep two small hierarchies and join them with a reference. The Remote holds a Device and only calls the Device's small interface. Now remotes and devices grow separately: 3 + 3 classes instead of 9.

✓ After
Remotedevicepress_power()AdvancedRemotepress_mute()«interface»Devicetoggle()TvRadiothe bridge
  • extends (is a)
  • implements
  • has a / holds
Remotes and devices are separate hierarchies joined by one link. Add either side freely.

Who is who

Remote (abstraction)
The high-level control. Holds a device.
AdvancedRemote
Refines the abstraction with extra buttons.
Device (implementation)
The small interface: toggle(), name.
Tv, Radio
Concrete devices.

Build it in steps

  1. 1Find the two dimensions that vary.
  2. 2Define the small interface for the lower dimension.
  3. 3Let the upper class hold a reference to it.
  4. 4Extend each side independently.
4

Watch it run

Step through the calls. Tap an arrow to jump to it.

ClientAdvancedRemoteRadio1press_power()2toggle()3'Radio on'4press_mute()5'Radio muted'
Step 1/5

The client presses a button on an AdvancedRemote.

press_power()
5

The code

Python and Java. Try writing the classes yourself from the diagram first.

class Tv:
    name = "TV"

    def __init__(self):
        self.on = False

    def toggle(self):
        self.on = not self.on
        return self.name + (" on" if self.on else " off")


class Radio(Tv):
    name = "Radio"


class Remote:                                # the abstraction holds a device (the bridge)
    def __init__(self, device):
        self.device = device

    def press_power(self):
        return self.device.toggle()


class AdvancedRemote(Remote):
    def press_mute(self):
        return self.device.name + " muted"


def demo():
    return [Remote(Tv()).press_power(), AdvancedRemote(Radio()).press_power(), AdvancedRemote(Radio()).press_mute()]

What you gain

  • Two dimensions grow separately: sum of classes, not product
  • Swap the implementation at run time

What it costs

  • More planning up front
  • Not worth it if only one dimension varies

You have already met it in

  • JDBC: your code calls the same API, the driver differs per database
  • Shape and Colour hierarchies in graphics code
  • Logger front-ends with swappable back-ends (SLF4J)

Often mixed up with

  • AdapterAdapter fixes two existing interfaces after the fact; Bridge is planned up front so two parts can evolve separately.
  • StrategyStrategy swaps one behaviour inside a class; Bridge splits a whole class family in two.
6

Make it stick

Model Shape (Circle, Square) and Renderer (Vector, Raster). Show that adding a Triangle needs one class and adding an OpenGL renderer needs one class.

Confidence