Yup, the original gang-of-four one. Now obviously this isn’t the first book on design patterns I’ve read (I’d hope that there’s not many people writing software for a living that have not at-least skimmed through one) but it is the first one I’ve read in a while, and seemed a good successor to the Refactoring book (and a good predecessor to Refactoring To Patterns, which is also on my reading list).
There’s probably not much I can say about this book that hasn’t already been said many times, it can be very verbose, as it’s intended audience is someone who has no knowledge of these patterns (though that helps for some of the patterns that were less familiar to me) but it covers each pattern well, particularly valuable are the sections for each patten that explain why you would use it (often comparing to other patterns) and what considerations you should use when choosing a pattern. This latter section tends to go deeper than ‘good’ and ‘bad’ points about the pattern, often explaining the effect it will have on the larger system.
The examples are in C++ and Smalltalk, and even though I’ve never seen Smalltalk before they were easy enough to follow (and each example has a UML-esqe diagram to resolve any ambiguity). The Smalltalk examples are occasionally relevant even to a C++ programmer, since Smalltalk has lambdas and closures which were not available in C++ when the book was written, but are now (as long as you’re lucky enough to be able to use C++ 11 or greater), and there are a few examples where the pattern was described in Smalltalk because it would be awkward in C++ thanks to the lack of these features.
Reading this book made me realise just how much of the code I read and write uses these patterns, even if the code doesn’t make mention of the actual pattern (though I have resolved to use the names explicitly going forward) it also helped solidify some of the finer details that I was unfamiliar with (the difference between state and strategy, for example).