A Bridge Too Far

I was looking through my Gang of Four design patterns book recently, a book I last cracked open many years ago. Maybe it’s the experience I’ve had since then, but one pattern jumped out at me in a way that I don’t remember happening before: the Bridge pattern.

And not in a good way.

The pattern purportedly heads off this kind of class hierarchy, where the abstract public classes are in blue, and the concrete classes are in black:

Regular Abstraction Layer

The idea above being that for every public, abstract class, like Window and its subclass CircleWindow, you’ll need a full array of concrete classes hanging off of it, like OSXWindow and OSXCircleWindow. That can lead to a proliferation of classes, even in the two-level deep hierarchy shown above.

The Bridge pattern makes it unnecessary to have any more than a single array of concrete classes:

Body Abstraction Layer

But it does this by making a very brittle assumption: the only concrete method implementations that will ever be needed anywhere in the system can be put into that base implementation class. (Here, WindowImp.)

The example given in the book is drawing. The concrete classes implement DrawText() and DrawLine(), and everything else can be derived from that—geometric shapes, icon borders, etc.

I have no faith in that. There isn’t a single complex architecture I’ve worked on—and why would you use this for very simple architectures?—where you can comfortably put everything you need in a base class like that. You will always need weird, subclass-specific logic, and tossing such things into a base class leads to confusion, lack of proper separation, and maintenance headaches.

“Oh,” you say, “well then, make an Imp class hierarchy and….” Dammit, multiple hierarchies are what this pattern was supposed to solve!