Preface
When considering this book, some of you will ask: Another book on design patterns in C++? Why that, and why now? Hasn’t everything there is to know about design patterns been written already?
There are several reasons why yet another book on design patterns has been written, but first of all, this is very much a C++ book—this is not a book on design patterns in C++ but a book on design patterns in C++, and the emphasis sets it apart. C++ has all the capabilities of a traditional object-oriented language, so all the classic object-oriented design patterns, such as Factory and Strategy, can be implemented in C++. A few of those are covered in this book. But the full power of C++ is realized when you utilize its generic programming capabilities. Remember that design patterns are frequently occurring design challenges and the commonly accepted solution—both sides are equally important in a pattern. It stands to reason that when new tools become available, new solutions become possible. Over time, the community settles on some of these solutions as the most advantageous overall, and a new variation of an old design pattern is born—the same challenge but a different preferred solution. But expanding capabilities also opens up new frontiers—with new tools at our disposal, new design challenges arise.
Others may expect to find a new coming of the classic book “Design Patterns: Elements of Reusable Object-Oriented Software”. This ‘isn’t that book, and I do not believe that the time is right for such a book. The “Gang of Four” book was novel, even revolutionary, and it introduced the language of design patterns into the broad programming community. This has been done once and for all. It also established the neat taxonomy of design patterns, and that part has not aged nearly as well: as our pattern vocabulary expanded, we found patterns that do not fit easily into a particular category. We also extended the notion of design patterns beyond object-oriented programming and found that some of these patterns strongly resemble their object-oriented cousins while others are entirely new and different. Furthermore, in C++ and other languages with significantly different capabilities, a pattern that addresses the same need may look totally different. The bottom line is the original classification of patterns, while still useful, by now has more exceptions than typical examples, and the pattern landscape became too divergent for a new taxonomy that would not seem far too artificial. Maybe in time, as we develop the art further, new trends will emerge from the bird’s eye view of the expanded pattern landscape, but it has not happened yet.
This book has less ambitious but very practical goals. In this book, we focus on design patterns where C++ has something essential to add to at least one of the two sides of the pattern. On the one hand, we have patterns such as Visitor, where the generic programming capabilities of C++ allow for a better solution. That better solution was made possible by new features that were added with the evolution of the language from C++11 to C++17. On the other hand, generic programming is still programming (only the execution of the program happens at compile time); programming requires design, and design has common challenges that are not all that dissimilar to the challenges of traditional programming. Thus, many of the traditional patterns have their twins, or at least close siblings, in generic programming, and we largely focus on those patterns in this book. A prime example is the Strategy pattern, better known in the generic programming community by its alternative name, the Policy pattern. Also, as new features are added to the language, it can offer solutions to new problems or new solutions to old problems, and both of these eventually develop into design patterns. This is the case with the C++ coroutines, which make an appearance in the last chapter.
Finally, a language as complex as C++ is bound to have a few idiosyncrasies of its own that often lead to C++-specific challenges that have common, or standard, solutions. While not quite deserving of being called patterns, these C++-specific idioms are also covered in this book.
A few words about the changes for the second edition: first of all, there is a new chapter on patterns for concurrency. All examples are updated to use C++17 or C++20 wherever it makes sense, but never gratuitously. Many patterns, idioms, and examples demonstrating their use were updated with recent developments and advances – the result of the work of the C++ programming community in the last few years.
All that said, there are three main reasons why this book has been written:
- To cover C++-specific solutions for otherwise general, classic design patterns
- To show C++-specific pattern variants that occur when old design challenges arise in the new domain of generic programming
- To keep our patterns up to date with the language’s evolution