OOD Fundamentals
OOP Foundations
SOLID Principles
Structural Patterns
Behavioral Patterns
Classic OOD Problems: Part 1
Classic OOD Problems: Part 2
Singleton and Object Pool
Some resources should exist exactly once in your entire application. A configuration manager that reads settings from a file, a logger that writes to a single log destination, or a metrics collector that aggregates counters: creating multiple instances of any of these leads to bugs. Two configuration managers might hold conflicting values. Two loggers might interleave output or fight over a file handle. The Singleton pattern exists to prevent this: it guarantees that a class has exactly one instance and provides a global access point to it.

How Singleton Works
The core mechanism has three parts: a private constructor that prevents outside code from calling __init__ directly, a class-level variable that stores the single instance, and a class method that returns that instance (creating it on the first call).
Every call to ConfigManager() returns the same object. The first call creates it; every subsequent call skips creation and hands back the existing instance.
Lazy vs. Eager Initialization
The example above uses lazy initialization: the instance is created the first time someone asks for it. This is useful when creating the instance is expensive (loading a config file, opening a network connection) and you want to defer the cost until it is actually needed.
Eager initialization creates the instance at class load time, before any code requests it. In Python, you can achieve this by instantiating at module level:
Eager initialization is simpler and avoids thread-safety issues (the instance exists before any concurrent code runs), but it pays the creation cost even if the singleton is never used.
In Python, the module system itself acts as a natural singleton mechanism. When you import a module, Python caches it: every subsequent import returns the same module object. A module-level variable is effectively a singleton without any special pattern.
When Singleton Makes Sense
Use Singleton when all three conditions are true: the resource is genuinely one-of-a-kind (one configuration, one logger destination), creating multiple instances would cause bugs or conflicts, and the resource needs to be accessible from many parts of the codebase. If even one condition is missing, Singleton is probably the wrong choice.