Wzorzec projektowy Singiel (ang. Singleton) pozwala na utworzenie tylko jednej instancji obiektu danej klasy. Podobnie jak zmienne globalne, instancja Singla jest widoczna w całym programie i każdy komponent ma do niej dostęp. Używa się go głównie do przechowywania konfiguracji programu oraz utrzymania połączenia z bazą danych.
IMPLEMENTACJA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?php class Singleton { private static $instance; public static function getInstance() { if (!isset(static::$instance)) { static::$instance = new static(); } return static::$instance; } private function __construct() {} private function __clone() {} private function __wakeup() {} } $singleton = Singleton::getInstance(); |
Statyczna metoda getInstance sprawdza czy instancja obiektu tej klasy jest już utworzona, jeśli tak, to zwraca referencję do niej, a jeśli nie, to w razie potrzeby tworzy ją. Aby zablokować tworzenie kolejnych, tych samych instancji konstruktor klasy deklaruje się jako prywatny (private) lub chroniony (protected). Dodatkowo obiekt zabezpieczony jest przed klonowaniem i deserializacją.
PRZYKŁAD
Klasa Singla o nazwie DB posłuży do nawiązania połączenia z bazą danych. Funkcja connection zwróci uchwyt połączenia, który będzie można użyć w dowolnym fragmencie kodu programu, na przykład w celu wykonania kwerendy SQL.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<?php // DB.php // Singleton class DB { private static $instance; private $config; private function __construct() {} private function __clone() {} private function __wakeup() {} public static function getInstance() { if (!isset(static::$instance)) { static::$instance = new static(); // or new DB() } return static::$instance; } public function connection($config) { $this->config = $config; try { $pdo = new PDO( 'mysql:host='.$this->config['host'].';dbname='.$this->config['name'], $this->config['username'], $this->config['password'] ); echo 'Connection successful ...'; return $pdo; } catch(PDOException $error) { echo $error->getMessage(); } } } |
Teraz możemy przetestować wzorzec:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php spl_autoload_register(function ($class) { include $class . '.php'; }); $config = array( 'host' => 'localhost', 'username' => 'root', 'password' => '**********', 'name' => 'test', ); $db = DB::getInstance(); $pdo = $db->connection($config); |
Spróbuj jeszcze sklonować obiekt:
1 |
$pdo2 = clone $pdo; |
Oczywiście, będzie to niemożliwe 🙂 Wyświetli się wyjątek:
Fatal error: Uncaught Error: Trying to clone an uncloneable object of class PDO in …
Przykład na GitHub →