The Singleton pattern models a class whose application-wide collection contains at most one object. It controls creation and supplies a shared access point when the object is needed. section 14.0 section 14.1
Why a global variable is not enough
A global ExecutivePass appears to provide one pass, but callers can copy it or explicitly construct another ExecutivePass. The result is duplicated keys, conflicting holders, and an additional global pass. Global state also permits unexpected changes and can create ordering problems during application startup. section 14.1.2
A controlled Singleton implementation:
- Stores the only object in a private class variable such as _instance, initially None. section 14.1.3
- Exposes a class method such as obtain() as the access point, creating the object lazily when needed. section 14.1.3
- Rejects explicit construction by overriding __new__(), and rejects shallow and deep copies through __copy__() and __deepcopy__(). section 14.1.3
- Provides delete() to clear the stored instance so a later call can create a new one. section 14.1.3
ExecutivePass after refactoring
ExecutivePass.obtain("Ron") and ExecutivePass.obtain("Sal") return the same pass. After ExecutivePass.delete(), obtain("Pat") creates a new pass. Assigning Pat's reference to Leo still leaves one object; calling ExecutivePass() directly raises an exception. section 14.1.3 section 14.1.4
Figure 14.2 A well-designed singleton object. The private class variable _instance is a reference to the singleton object if it exists, or None otherwise. The public class method obtain() returns a reference to the singleton object. It first creates the singleton if it doesn’t already exist.
Use the object diagram to trace _instance, obtain(), lazy creation, and the singleton's global access point. section 14.1.3
Multithreaded code requires additional care: simultaneous checks of an empty _instance can allow multiple threads to create objects. Race-condition avoidance is deferred to multithreaded design. section 14.1.4





