I think you’re missing the point here. As the GOF authors state many times, this is all about a way of DISCUSSING common idioms in software designs. As someone points out here, James Coplien wrote an excellent book entitled Advanced C++ Programming Styles and Idioms long before the GOF published Design Patterns. One could look at Copliens book as an example of how to implement several common design patterns in a specific language: C++. I found it immensely valuable in my daily work at the time.
Depending on the support offered in the language and the run-time libs, there may be little if anything required to implement any given design pattern other than using one set of interfaces over another.
As a case in point, back in 1980, I wrote some code to implement something that eventually seemed highly constrained by the problem context itself — which if you read Christopher Alexander’s book A Timeless Way of Building (whose works were used in large part as the inspiration behind GOF’s efforts) you’ll see that’s exactly what he was pointing at.
This bit of code was looked upon by most of the developers there (including me) as butt-ugly and in desperate need of “cleaning up”. But try as they might, nobody was able to come up with a better solution. Later on, when I began learning C++ and saw how classes worked, it dawned on me that the bit of code I implemented back in 1980 perfectly reflected the semantics behind how constructors support the instantiation of instances in C++.
I had come up with an abstraction for containing resources related to different parts of a large chunk of code, that were in fact fairly modular. I realized that each of these “chunks” needed three independent sections in order to run properly: one section to initialize the resources in that “chunk”, and you had to run all of the “initialization” sections first before you could do anything else; one section that was used to manage the things inside that “chunk”; and a third section that was used to cleanly shut-down and free-up the resources when a given “chunk” was no longer needed. The fact that this code resided in ROM and that there could be several “instances” of it at run-time meant this code was analogous to a class, and the blocks of data used to maintain the current state of each of them represented individual objects or instances. The first section is analogous to a “constructor”, the third is a “destructor”, and the middle part supported all of the behavioral interfaces. I had no idea what I had invented at the time, only that it worked. And doing it this way — without compiler support — was, as I said, truly butt-ugly! It would look just as bad if you write the same code in C or any other non-OOP language today.
Because the things in the GOF book were written based on ~10 years of experience with actual OOP languages (eg., Smalltalk), they didn’t see a need to include patterns for managing classes themselves, because the languages were already incorporating those patterns in their design. But one could have written a pattern description based on the code I wrote in 1980 that explained how classes and objects work.
By the time the GOF book was published, people were already using the terms “class” and “object” to discuss a particular coding pattern that implements a distinct behavior, and that happened to be supported directly within more and more languages (like C++).
You did not need to write code to implement this design pattern in C++ because the language already supported it. You merely talked about “classes” and “objects” as if everybody knew what you were referring to. And at the time, a lot of people actually had trouble distinguishing between the two, believe it or not! (A class is an abstraction, and an object is an instance of a class.)
You can talk about “Singletons” without needing to know how they’re implemented. Everybody knows what you’re talking about, whether the language or run-time library supports them directly or not.
So I disagree with your premise — we cannot “get over” talking about classes, objects and singletons any more than we can “get over” talking about integers, floats, and strings, and the operators and functions that modify them. How are you going to refer to a bidirectional priority-based queue in a design discussion? Do you get confused when referring to the sin of a double that represents an angle rather than the algorithm used to compute it? Or the discriminant of an integer array? Or the spectral components of a 1024 element data sample obtained by something like an FFT? Do you even give the slightest thought to how they’re implemented? Most of the time, you couldn’t care less. These are references to specific design patterns, like a finger pointing at the moon, not how they’re implmented.
Design patterns are a way to talk about abstractions, not how they’re implemented. That’s why the GOF completely avoided any implementation examples in their original book. And yet, there have been plenty of books published subsequently that included both language and platform-specific implementations just so people could copy-and-paste code that would help them build those things without having to think about them much. A lot of that same code is still around today, even though the languages and/or run-time libraries now support a lot of these mechanisms intrinsically.
And many of them you can’t even put into a library unless the language supports generics or parameterized types, so you’re stuck implementing them inline in your code.
What we CAN “get over” is misunderstanding what the whole purpose of the GOF’s work was about. Go back and read Alexander’s book and you may get a better idea of where GOF was coming from. (BTW, GOF was a team of four guys who took on the task of documenting the efforts of several dozen people who spent a lot of time working through and refining the approach that was eventually documented in their book. It’s inaccurate to credit them individually with this effort; there were lots of people who were involved in what became quite a landmark work at the time. That’s also why they’re often referred to in the abstract as GOF rather than by name — GOF is sort of a pattern name itself that refers to an entire team and approach they took that was adapted from the work Alexandar did earlier. See the later publications from POPL conferences to see how their efforts impacted future work.)