🧩 Singleton パターン
✅ 設計意図
- ロガーや設定クラスのインスタンスを1 つだけ生成し再利用
- グローバルアクセスを提供しつつ、状態を一元管理
✅ 適用理由
- 「同じものをどこからでも使いたい」ケースに最適
- ログ形式の統一、設定の集中管理が容易になる
✅ 向いているシーン
- ログ・設定・キャッシュ・DB 接続など、共有状態が必要なユーティリティ
✅ コード例
- 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}")
✅ 解説
このコードは Singleton
パターン を使用して、Config
と Logger
のインスタンスがアプリケーション全体で一意であることを保証している。
Singleton
パターンは、クラスのインスタンスが 1 つだけであることを保証し、そのインスタンスへのグローバルなアクセスを提供するデザインパターン。
1. Singleton パターンの概要
- Singleton: クラスのインスタンスを 1 つだけ生成し、それをグローバルに提供する
- このコードでは
Config
とLogger
が該当
- このコードでは
- Client:
Singleton
インスタンスを利用するクラス- このコードでは
OrderService
が該当
- このコードでは
2. 主なクラスとその役割
Config
Singleton
クラス- アプリケーションの設定を管理
- 環境変数
DEBUG_MODE
を基にデバッグモードの有効/無効を判定
Logger
Singleton
クラス- ログ出力機能を提供
- デバッグモードが有効な場合にデバッグログを出力
OrderService
- クライアントクラス
Logger
を利用して注文作成時のログを出力
3. UML クラス図
4. Singleton パターンの利点
- インスタンスの一意性: アプリケーション全体で 1 つのインスタンスのみを保持
- グローバルアクセス:
getInstance
メソッドを通じて、どこからでもインスタンスにアクセス可能 - リソースの節約: 必要に応じてインスタンスを生成(遅延初期化)することで、リソースを節約
警告
- テストの難しさ: グローバルな状態を持つため、ユニットテストでモックや依存性注入が難しくなる場合がある
- 多用のリスク:
Singleton
を多用すると、コードが密結合になり、保守性が低下する可能性がある
この設計は、アプリケーション全体で共有されるリソース(例: 設定やログ機能)を管理する際に非常に有効である。ただし、適切な場面で使用することが重要。