Unless you’ve been living under a rock, you know how important and influential the GoF Design Patterns book book has been. If you have been living among the rocks, do yourself a favor and get a copy of the book. It’s considered prerequisite reading for software developers these days. Interviewers love to hear you mention one or two of these patterns by name (in the appropriate context, of course), and just thinking about design in this way will make you a better programmer.
In a previous article we started to look at some design patterns. (We didn’t get too far, but hey, this is not easy stuff!) Coplien’s “Envelope/Letter” pattern can be used to give a unified interface to a set of objects, even when the behavior of the objects might change when they’re modified or combined in some way. In our case, the sum of an integer with a real number is usually a real number. How does this pattern relate to some more familiar ones from the GoF book?
Bridges and Envelopes
Coplien’s Envelope/Letter pattern does something we’ve talked about in vague terms, but we haven’t come out and said it boldly:
The Envelope/Letter pattern, or Bridge pattern in GoF terms, allows us to decouple the interface of an object from its implementation.
So what exactly does that mean? The numbers code I put up as
and discussed in the previous post used a single, unified interface (that of
Number class) but different behaviors (the implementations) were provided
by the “letter” classes
GoF call this the bridge pattern. The “bridge” here is the separation between client interface and its implementation or implementations. For example, clients only saw the envelope in the previous example, but the letter was managed (even switched out!) by its internals.
Dumb jokes about computer scientists
It’s often said that a computer scientist is a person who believes that every problem can be solved by adding an extra layer of indirection. Whether or not that’s true (dubious, I say!) you must admit that the Bridge pattern is pretty much all about introducing an external layer of indirection. This allows implementations to change without breaking client code, or on the other hand, the interface can change without affecting the implementation too much.
Pimpl and OOP
When there’s exactly one, fixed implementation, this pattern is often referred to as Pimpl in the C++ world: Pimpl stands for "pointer to implementation." Most often this idiom is not exactly used for design purposes, but to reduce compilation times. By structuring your program correctly, you need only rely on header files dealing with the interfaces you use, and not ones that specify implementation. These header files tend to change less often (and you’re including fewer headers in general) so careful use of the Pimpl can greatly speed up compilation times for larger projects. (Having said that, there are some other benefits: better encapsulation, shielding your clients from changes in implementation, and so forth.)
Lots of people have written about these patterns more eloquently than I have, and especially about the Pimpl patter as it relates to C++. I highly recommend anything by Herb Sutter, who writes about the Pimpl idiom itself and also its use in C++11. (Short version: smart pointers make it easier, safer, and better!)
As a final note, it seems to me that the Pimpl idiom, and indeed the bridge pattern itself, doesn’t really have anything to do with object oriented programming. Like many of the GOF patterns, it’s useful in an OOP environment, but it’s also useful in other paradigms. Many projects these days seem to follow the C++ standard library style of "generic programming,“ marked by extensive use of templates together with clever use of the facilities afforded by the newer C++ standards. These projects can use the Pimpl idiom in the same way, and get the same benefits, as an object oriented project can. So, in this sense, these are software patterns that cross the "programming style” divide.
Approx. 671 words, plus code