Singleton Pattern¶
Category: Creational Pattern
Overview¶
Ensure a class has only one instance and provide a global point of access to it. This pattern restricts instantiation of a class to a single object, useful for managing shared resources like configuration settings, logging, or database connections.
Usage Guidelines¶
Use when:
- Only one instance of a class should exist in the system
- The instance needs to be accessible from anywhere in the application
- Managing shared resources like database connections, thread pools, or caches
- Centralized configuration that must be consistent across the application
Avoid when:
- Singletons make unit testing harder due to global state
- Creates hidden dependencies throughout the codebase
- Complex synchronization needed for thread-safe access
- You might need multiple instances in the future
Implementation¶
from threading import Lock
from typing import Any
class SingletonMeta(type):
"""Metaclass that creates a Singleton base class.
This implementation is thread-safe and ensures that only one instance
of the class exists across multiple threads.
"""
_instances: dict[type, Any] = {}
_lock: Lock = Lock()
def __call__(cls, *args: Any, **kwargs: Any) -> Any:
"""Create or return the singleton instance.
Args:
*args: Variable length argument list.
**kwargs: Arbitrary keyword arguments.
Returns:
The singleton instance of the class.
"""
with cls._lock:
if cls not in cls._instances:
instance = super().__call__(*args, **kwargs)
cls._instances[cls] = instance
return cls._instances[cls]
class DatabaseConnection(metaclass=SingletonMeta):
"""Example singleton class representing a database connection.
This class can only have one instance throughout the application lifecycle.
"""
def __init__(self) -> None:
"""Initialize the database connection."""
self.connection_string = "Connected to database"
self.queries_executed = 0
def execute_query(self, query: str) -> str:
"""Execute a database query.
Args:
query: The SQL query to execute.
Returns:
Result message indicating query execution.
"""
self.queries_executed += 1
return f"Executed: {query}"
Usage¶
# Metaclass-based singleton
db1 = DatabaseConnection()
db2 = DatabaseConnection()
assert db1 is db2 # True - same instance
print(db1.execute_query("SELECT * FROM users"))
Trade-offs¶
Benefits:
- Controlled access through single point of control
- Reduced namespace pollution while providing global access
- Lazy initialization with instance created only when first needed
- Thread safety with proper implementation ensuring safe concurrent access
Drawbacks:
- Introduces global state making code harder to reason about
- Hard to mock or replace in unit tests
- Classes depending on singletons have hidden dependencies
- Requires careful synchronization in multi-threaded environments
Real-World Examples¶
- Logging systems used throughout application
- Configuration managers centrally accessible
- Database connection pools
- Cache managers shared across application
Related Patterns¶
- Factory Method
- Abstract Factory
- Facade
- State
- Flyweight
API Reference¶
design_patterns.creational.singleton
¶
Singleton Pattern Module
The Singleton pattern ensures that a class has only one instance and provides a global point of access to that instance. This is useful for managing shared resources like configuration settings, logging, or database connections.
This module demonstrates three implementations: 1. Metaclass-based Singleton (thread-safe) 2. Decorator-based Singleton 3. Module-level Singleton (Pythonic approach)
Example
Using the metaclass-based singleton:
ConfigurationManager
¶
Pythonic singleton using class attributes.
This implementation uses a class attribute to store the single instance, which is a common Python idiom for singletons.
Source code in src/design_patterns/creational/singleton.py
__init__()
¶
__new__()
¶
Create or return the singleton instance.
Returns:
| Type | Description |
|---|---|
ConfigurationManager
|
The singleton instance. |
Source code in src/design_patterns/creational/singleton.py
get(key, default=None)
¶
Get a configuration value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
The configuration key. |
required |
default
|
Any
|
Default value if key not found. |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
The configuration value or default. |
Source code in src/design_patterns/creational/singleton.py
set(key, value)
¶
Set a configuration value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str
|
The configuration key. |
required |
value
|
Any
|
The configuration value. |
required |
DatabaseConnection
¶
Example singleton class representing a database connection.
This class can only have one instance throughout the application lifecycle.
Source code in src/design_patterns/creational/singleton.py
Logger
¶
Example singleton logger class using decorator pattern.
This logger ensures all parts of the application use the same logging instance.
Source code in src/design_patterns/creational/singleton.py
SingletonMeta
¶
Bases: type
Metaclass that creates a Singleton base class.
This implementation is thread-safe and ensures that only one instance of the class exists across multiple threads.
Source code in src/design_patterns/creational/singleton.py
__call__(*args, **kwargs)
¶
Create or return the singleton instance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*args
|
Any
|
Variable length argument list. |
()
|
**kwargs
|
Any
|
Arbitrary keyword arguments. |
{}
|
Returns:
| Type | Description |
|---|---|
Any
|
The singleton instance of the class. |
Source code in src/design_patterns/creational/singleton.py
singleton_decorator(cls)
¶
Decorator that converts a class into a singleton.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The class to convert into a singleton. |
required |
Returns:
| Type | Description |
|---|---|
type
|
A wrapper class that implements singleton behavior. |