Software! Math! Data! The blog of R. Sean Bowman
The blog of R. Sean Bowman
January 14 2016

In the last post we learned about the bridge pattern and its pedigree from the envelope/letter pattern of Coplien (and probably other sources, I’m just not an expert enough to know about them all!) Now let’s compare it to some other patterns and examine the differences and similarities. It often turns out that the rationale behind implementing some pattern is crucial, even when the different patterns themselves might look substantially the same in code.

The Bridge pattern seems very similar to some other patterns you might know about. For example, a common need in software development is to adapt a given piece of code to a new interface. This pattern is called, appropriately, the Adapter pattern. It seems similar at first because the adapter class provides the desired interface to clients while delegating the hard work to an internal implementation (often one that somebody else wrote or was otherwise provided to you).

Bridge vs. Adapter

But there is a major difference between the Bridge and Adapter patterns, at least philosophically. The adapter pattern is a way to make interfacing with other code less painful. It’s done after the fact – you’ve already decided (or been told) to use some particular library. You need an interface on top that you/your clients/whoever else can use.

With the adapter pattern, you have total control over both interface and implementation, and neither necessarily comes first. They’re designed together, to work together, and in the case of multiple envelopes or multiple letters, they have to be thought through quite a bit before you can be sure you’re writing the right code.

Adapter Pattern

An adapter is used after the implementation has already been given to you, and the purpose is to make things easier on you or your colleagues. Bridges, on the other hand, offer more flexibility at the cost of some up front design.

Bridge vs. Strategy

Now this one is a little harder to articulate. The Strategy pattern allows for pluggable implementations hiding behind a uniform interface. As an example, we might have several different algorithms with different performance characteristics, and we may want to allow the user to choose the best one for their circumstances. This can be achieved by swapping out implementations that sit behind a uniform interface. But again, note that the philosophical reasons for doing so are different from using a bridge. Bridges change implementation in response to domain circumstances (the sum of a real number and an integer is generally a real number, for example). Strategies are different ways of doing the same thing, possibly with some trade offs.

Strategy vs. State

Strategy and State are another pair of patterns that can be easily mixed up. Whereas strategy lets you choose from several implementations, the Strategy pattern is generally used to change implementations several times over the lifetime of the application. One important use of it is avoiding large switch statements or if/then/else conditions.

Many years ago I had a great use for the Strategy Pattern. I was writing some simulations to investigate multi-agent systems. My simulations were of a group of very simple robots performing the simple task of pushing boxes to the shelves where they’re needed. The robot brain is essentially a state machine: it spends time wandering around looking for boxes, then it finds one, and then it wanders some more looking for a shelf to put the box on. Instead of writing that code as a big switch statement or series of if/then/elses, we simply switch out the state object when a “state change” occurs, such as the robot spotting a box. You can view the code here; there are three states the robot can be in, and in each one the robot acts slightly different.

Strategy and State

The strategy pattern is a way of choosing between different ways of doing the same thing, whereas the state pattern is used to simplify code by encapsulating behaviors in objects that can be switched out at the proper times.

As with both of these, our intent is not to decouple the interface from its implementation as with the Bridge pattern.

Finally, let me reference the (pretty good) Wikipedia pages on these subjects:

Approx. 698 words, plus code