ConceptDifficulty: Intermediate3 min

Bridge Pattern: Separating What Something Does From How It Is Done

Three shapes and two renderers need six subclasses; a bridge needs five classes.

The Bridge pattern splits a class that varies in two independent ways into two class hierarchies, one for what the object does and one for how it does it, and connects them with a single reference. Each hierarchy then grows on its own. This card covers the problem that calls for it, the intent, and when it fits.

The problem is two dimensions of variation, two independent ways a class can differ. Shapes can be circles, squares or triangles, and each can be drawn by a vector or a raster renderer. Using inheritance for both means a subclass for every pair, and the count is the product of the two.

A subclass per pair, and two hierarchies joined by a reference

Without the patternthree shapes times two renderers

text
VectorCircle   RasterCircle
VectorSquare   RasterSquare
VectorTriangle RasterTriangle

There are six classes, and a third renderer adds three more. Each pair repeats the drawing code for its renderer.

With the patternthree shapes plus two renderers

py
class Shape:
    def __init__(self, renderer: Renderer):
        self._renderer = renderer


Circle(VectorRenderer())

There are five classes, and a third renderer adds one. Each shape holds a renderer and calls it.

The Gang of Four state the intent as: decouple an abstraction from its implementation so that the two can vary independently. The abstraction is the side the client uses, the shape. The implementation is the side it delegates to, the renderer, and the reference from one to the other is the bridge.

With M variants on one side and N on the other, inheritance needs M times N classes and a bridge needs M plus N. The difference is small at three and two, six against five, and grows quickly: at five and four it is twenty against nine.

Bridge is one of seven structural patterns, the family that composes classes and objects into larger structures.

The structural family, with this pattern marked
PatternWhat it does
AdapterGives an existing object the interface a client expects.
Bridge (this topic)Separates an abstraction from its implementation so both can vary.
CompositeTreats a tree of objects and a single object the same way.
DecoratorAdds behaviour by wrapping an object in another with the same interface.
FacadePuts one simple interface in front of a complex subsystem.
FlyweightShares the common part of many small objects to save memory.
ProxyStands in for an object to control access to it.

Bridge and Adapter both put an interface between two classes, and they differ in when. An adapter is added after the fact, to make an existing class fit. A bridge is designed up front, so that two hierarchies never have to know about each other's subclasses.

Bridge

Use it when

  • A class varies in two independent ways, and subclassing both would multiply the classes.
  • The implementation should be chosen or swapped at run time, such as a driver picked by configuration.
  • Changes to the implementation side must not force the client's code to recompile or change.

Avoid it when

  • Only one dimension varies, so the second hierarchy would hold a single class.
  • The two dimensions are not independent, and some pairs make no sense together.
  • The goal is to make an existing class fit an interface, which is Adapter.

← → move through sections and cards