Menu
Coddy logo textTech

Singletonパターン

CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 71/91。

Singleton Patternは、アプリケーションのライフサイクル全体を通じてclassがinstanceを1つだけ持つことを保証する生成デザインパターンです。また、そのinstanceへのグローバルなアクセスポイントも提供します。

このパターンは、データベース接続、設定マネージャー、ロガーなど、システム全体でアクションを調整するオブジェクトが正確に1つ必要な場合に役立ちます。これらのインスタンスを複数作成すると、リソースを無駄にしたり、一貫性のない動作を引き起こしたりする可能性があります。

PHPでSingletonを実装する方法は次のとおりです:

<?php
class Database {
    private static ?Database $instance = null;
    
    private function __construct() {
        // プライベートコンストラクタは直接のインスタンス化を防ぎます
    }
    
    public static function getInstance(): Database {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    public function query(string $sql): string {
        return "Executing: $sql";
    }
}

$db1 = Database::getInstance();
$db2 = Database::getInstance();

echo $db1 === $db2 ? "Same instance" : "Different instances";

出力:

Same instance

このパターンは、3つの重要な要素に基づいています。private constructornew を直接使用することを prevents し、static property は単一の instance を保持し、static method は最初の呼び出し時に instance を作成し、その後の呼び出しではそれを returns します。

Singleton を本当に堅牢にするには、cloning と unserialization も prevent する必要があります。

<?php
private function __clone() {}
public function __wakeup() {
    throw new Exception("Cannot unserialize singleton");
}
challenge icon

チャレンジ

簡単

Singleton Patternを使用して設定マネージャーを構築しましょう。実際のアプリケーションでは、通常、設定の単一の信頼できる情報源が必要です。複数の設定オブジェクトがあると、システム全体で一貫性のない動作につながる可能性があります。

コードを2つのファイルに整理します。

  • Config.php: Singleton Patternを実装するConfig classを作成します。設定マネージャーは次の要件を満たす必要があります。
    • 設定をprivate array propertyに保存する
    • settings arrayをemptyとしてinitializesするprivate constructorを持つ
    • 単一のinstanceをreturnsするstatic getInstance() methodを提供する
    • __clone()をprivateにすることでcloningをpreventする
    • 設定を保存するためのset(string $key, string $value): void methodを含める
    • keyに対応するvalueをreturnsし、keyが存在しない場合はnullをreturnsするget(string $key): ?string methodを含める
    • すべての設定をreturnsするgetAll(): array methodを含める
  • main.php: Config fileをincludeします。2つの入力、keyとvalueを受け取ります。

    Config instanceを取得し、key "app_name"とvalue "MyApp"を持つdefault settingを設定します。

    Config instanceへのsecond referenceを取得し(再度getInstance()を使用)、入力のkeyとvalueを使って別のsettingを設定します。

    最後に、Singletonが正しく動作していることを確認します。

    • 両方のreferenceがSame objectを指しているかどうかに基づいて、"Same instance: true"または"Same instance: false"をPrintします(比較には===を使用)
    • 保存されているsettingの総数を示す"Settings count: [count]"をPrintします(getAll()の結果に対してcount()を使用)
    • second referenceを通じてretrievedしたapp_name settingを示す"App name: [value]"をPrintします

このchallengeはSingleton Patternのcore benefitを示しています。getInstance()を何回callしても、常にSame objectが得られるため、アプリケーションのすべての部分が同じconfiguration stateを共有できます。

自分で試してみよう

<?php

require_once 'Config.php';

// 入力を読み取る
$key = trim(fgets(STDIN));
$value = trim(fgets(STDIN));

// TODO: Config インスタンスを取得し、"app_name" を "MyApp" に設定する

// TODO: getInstance() を再度使用して Config への2つ目の参照を取得する

// TODO: 2つ目の参照を使用して、入力からの $key と $value で設定を行う

// TODO: Singleton が機能していることを確認する:
// - Print "Same instance: true" or "Same instance: false" based on === comparison
// - Print "Settings count: [count]" showing total settings
// - 2つ目の参照を通じて取得した app_name を示す "App name: [value]" を出力する

?>
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: PHPオンラインコンパイラ