π§© Singleton Pattern
β Intentβ
- Ensure that classes like
Logger
orConfig
are instantiated only once and reused globally - Provide centralized control and access to shared state across the application
β Motivationβ
- Ideal for cases where "the same instance should be used everywhere"
- Helps unify log formatting and centralize configuration management
β When to Useβ
- When building utilities like logging, configuration, caching, or DB connections that require a shared, single state
β Code Exampleβ
- TypeScript
- PHP
- Python
class Config {
private static instance: Config;
private debugMode: boolean;
private constructor() {
this.debugMode = process.env.DEBUG_MODE === "true";
}
static getInstance(): Config {
if (!Config.instance) {
Config.instance = new Config();
}
return Config.instance;
}
isDebug(): boolean {
return this.debugMode;
}
}
class Logger {
private static instance: Logger;
private constructor() {}
static getInstance(): Logger {
if (!Logger.instance) {
Logger.instance = new Logger();
}
return Logger.instance;
}
log(message: string) {
console.log(`[LOG] ${message}`);
}
debug(message: string) {
if (Config.getInstance().isDebug()) {
console.log(`[DEBUG] ${message}`);
}
}
}
// ε©η¨δΎ
class OrderService {
createOrder(orderId: string) {
const logger = Logger.getInstance();
logger.log(`注ζδ½ζ: ${orderId}`);
logger.debug(`注ζθ©³η΄°: ${orderId}`);
}
}
<?php
class Config {
private static ?Config $instance = null;
private bool $debugMode;
private function __construct() {
$this->debugMode = getenv("DEBUG_MODE") === "true";
}
public static function getInstance(): Config {
if (self::$instance === null) {
self::$instance = new Config();
}
return self::$instance;
}
public function isDebug(): bool {
return $this->debugMode;
}
}
class Logger {
private static ?Logger $instance = null;
private function __construct() {}
public static function getInstance(): Logger {
if (self::$instance === null) {
self::$instance = new Logger();
}
return self::$instance;
}
public function log(string $message): void {
echo "[LOG] {$message}\n";
}
public function debug(string $message): void {
if (Config::getInstance()->isDebug()) {
echo "[DEBUG] {$message}\n";
}
}
}
class OrderService {
public function createOrder(string $orderId): void {
$logger = Logger::getInstance();
$logger->log("注ζδ½ζ: {$orderId}");
$logger->debug("注ζθ©³η΄°: {$orderId}");
}
}
import os
class Config:
_instance = None
def __init__(self):
self.debug_mode = os.environ.get("DEBUG_MODE") == "true"
@classmethod
def get_instance(cls):
if cls._instance is None:
cls._instance = Config()
return cls._instance
def is_debug(self):
return self.debug_mode
class Logger:
_instance = None
def __init__(self):
pass
@classmethod
def get_instance(cls):
if cls._instance is None:
cls._instance = Logger()
return cls._instance
def log(self, message: str):
print(f"[LOG] {message}")
def debug(self, message: str):
if Config.get_instance().is_debug():
print(f"[DEBUG] {message}")
class OrderService:
def create_order(self, order_id: str):
logger = Logger.get_instance()
logger.log(f"注ζδ½ζ: {order_id}")
logger.debug(f"注ζθ©³η΄°: {order_id}")
β Explanationβ
This code uses the Singleton
pattern to ensure that Config
and Logger
are instantiated only once across the application.
The Singleton
pattern guarantees a single instance and provides global access to it throughout the codebase.
1. Overview of the Singleton Patternβ
-
Singleton: A class that ensures a single instance and exposes a global access point
- In this example:
Config
andLogger
- In this example:
-
Client: Uses the singleton instance
- In this example:
OrderService
- In this example:
2. Key Classes and Their Rolesβ
-
Config
- A singleton class that manages application settings
- Uses environment variable
DEBUG_MODE
to determine if debug mode is enabled
-
Logger
- A singleton class that provides logging functionality
- Outputs debug logs only when debug mode is enabled
-
OrderService
- A client class that logs order creation via the shared
Logger
instance
- A client class that logs order creation via the shared
3. UML Class Diagramβ
4. Benefits of the Singleton Patternβ
- Unique Instance: Guarantees exactly one instance throughout the application
- Global Access: The instance can be accessed from anywhere using
getInstance
- Resource Saving: Enables lazy initialization to avoid unnecessary object creation
warning
- Testing Difficulty: Global state can make unit testing harder due to tight coupling and lack of dependency injection
- Risk of Overuse: Overusing Singletons can lead to tightly coupled code and reduced maintainability
This pattern is highly effective when managing shared resources like configuration or logging across an entire application.
However, careful and deliberate use is recommended to avoid the pitfalls of global state and tight coupling.