In one sentence: Singleton ensures a class has only one instance and provides a global point of access to it.
Real-world analogy
A country has exactly one government. It doesn't matter who asks — a citizen, a journalist, a foreign diplomat — the question "who's in charge here?" always resolves to the same institution. You never get handed a fresh government of your own; you get pointed to the one that already exists.
And here's the crucial part: you can't just found a second government because you feel like it. The constitution forbids it — the rule "there is only one" isn't a polite convention that everyone hopefully follows, it's enforced by the system itself. Even if a million people ask "who's in charge?" at the same time, they all end up talking to the same institution.
Notice also when a government forms: not before the country exists, but when it's first needed. Nobody sets up a parliament for an island with no inhabitants.
Mapping the analogy to the pattern:
- The government → the single instance.
- Asking "who's in charge?" → calling
instance()— the one global access point that always returns the same object. - The constitution forbidding a second government → the hidden constructor and deleted copy operations: the class itself enforces uniqueness, not a comment or a convention.
- Forming the government when first needed → lazy initialization: the object is created on the first
instance()call, not at program start.
Another angle: the office Wi-Fi router. Everyone in the building connects to the router — nobody unboxes a personal one per meeting. There's a well-known way to reach it (the network name), and IT makes sure a rogue second router can't appear and split the office onto two networks.
The problem
Some classes must have exactly one instance. The GoF book's classic examples: a system can have many printers, but only one printer spooler; one file system; one window manager. Two problems appear if you manage this by hand:
- A global variable doesn't stop a second instance. It makes one object easy to reach, but nothing prevents other code from constructing another — and now two spoolers are fighting over the same printer queue.
- Everyone needs to reach it. Passing the same object through ten layers of function parameters is painful, and a plain global can be reassigned by anyone.
The solution
Make the class itself responsible for its single instance — that's the whole trick:
- Hide the constructor so outside code can't call
newor create one on the stack. (GoF makes itprotectedto allow subclassing; if you don't need subclasses,privateis stricter and more common in modern C++.) - Add a static
instance()method that creates the object on first call and returns that same object forever after. The class intercepts every request for an object and always hands back the one and only.
In modern C++ this is famously easy — a local static variable inside instance() is initialized exactly once, and since C++11 that initialization is guaranteed thread-safe by the language. This is called the Meyers Singleton.
Structure
There is only one participant:
- Singleton — declares the static
Instance()operation that lets clients reach the unique instance, and is usually responsible for creating that instance itself. Clients access the singleton solely throughInstance().
C++ example
A minimal, thread-safe logger. Note the deleted copy operations — they close the last loophole for accidental duplicates.
#include <iostream>
#include <string>
class Logger {
public:
// The single global access point.
static Logger& instance() {
static Logger logger; // created once, thread-safe since C++11
return logger;
}
// Forbid copying — there must never be a second instance.
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
void log(const std::string& message) {
++count_;
std::cout << "[log #" << count_ << "] " << message << "\n";
}
private:
Logger() = default; // hidden: only instance() can construct
int count_ = 0;
};
int main() {
Logger::instance().log("App started");
Logger::instance().log("Loading config");
// Both names refer to the very same object:
Logger& a = Logger::instance();
Logger& b = Logger::instance();
std::cout << "Same object? " << std::boolalpha << (&a == &b) << "\n";
}[log #1] App started
[log #2] Loading config
Same object? trueThe counter keeps increasing across all call sites — proof that every instance() call hits the same object.
Note: The GoF book warns against the naive alternative — a global/static object — for a reason that still bites today: C++ doesn't define the initialization order of globals across translation units, so one global singleton using another during startup is undefined behavior roulette. The function-local static above dodges this: it's created on first use, not at program start.
When should you use it?
The GoF applicability list is short and precise. Use Singleton when:
- There must be exactly one instance of a class, reachable from a well-known access point — logging, configuration, a hardware interface, a connection pool.
- The sole instance should be extensible by subclassing, and clients should use the extended instance without code changes (this is why GoF returns a pointer from
Instance()and keeps the constructorprotected).
Pros and cons
Pros (GoF's consequences)
- Controlled access — the class has strict control over how and when clients reach the instance.
- Better than a global variable — no namespace pollution, and creation is lazy: the object is built on first use, not at program start.
- Refinable — you can subclass the singleton and configure the application with the extended instance.
- More flexible than static member functions — statics can't be
virtual, so a class made of static functions can never be polymorphic or allow multiple instances later.
Cons
- It's still a global variable with better manners — a hidden dependency everywhere it's used.
- Makes unit testing harder: you can't easily swap in a mock.
- Under-the-hood coupling: many "singletons" are really objects that should just be created once in
main()and passed down.
How to remember it
Memory hook: "The class is its own bouncer." Nobody gets to construct one — you ask the class, and it always points at the same instance. If you can say "there can be only one and the class enforces it," it's a Singleton. If you merely happen to create one, that's not the pattern — that's just an object.
Related patterns
- Abstract Factory, Builder, Prototype — GoF notes that many patterns are commonly implemented as singletons: one factory, one builder, one prototype registry.
- Facade — facades are often singletons too, since one front door is usually enough.
- Flyweight — looks similar (shared objects) but allows many shared instances, not one.