Poznajemy wzorzec projektowy singleton. Uczymy się zamieniać istniejącą już klasę na ten wzorzec. Do dzieła.
Oto nasza klasa:
<?php
class App {
public function run(){
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];
echo "Path: $path, Method: $method";
}
}
$app = new App();
$app->run();
Singleton oznacza, że może być tylko jedna instancja (obiekt) danej klasy. To piszemy:
<?php
class App {
private static $instance = null;
private function __construct(public $app_name)
{}
public static function getInstance(){
if (self::$instance == null){
self::$instance = new App("MY_APP");
}
return self::$instance;
}
public function run(){
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];
echo "Path: $path, Method: $method";
}
}
$app = App::getInstance();
$app->run();
Konstruktor prywatny, instancja jako pole statyczne. Zawsze będzie tylko jeden obiekt. Pytanie co z argumentami do konstruktora. Jeżeli są zaciągane np. z jakiegoś pliku konfiguracyjnego – nie ma problemu.
Jeżeli chcemy dać użytkownikowi możliwość ustawiania ich samemu należy olać konstruktor i napisać odpowiedni getter/setter:
class App {
private static $instance = null;
private $app_name;
private function __construct()
{}
public static function getInstance(){
if (self::$instance == null){
self::$instance = new App();
}
return self::$instance;
}
public function getName(){
return $this->app_name;
}
public function setName($name){
$this->app_name = $name;
}
public function run(){
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$method = $_SERVER['REQUEST_METHOD'];
echo "Path: $path, Method: $method";
}
}
$app = App::getInstance();
$app->run();
$app->setName("my_app");
echo $app->getName();
//my_app
$app2 = App::getInstance();
echo $app2->getName();
//my_app
var_dump($app === $app2);
//true
Jak widać cały czas mamy do czynienia z jedną instancją, choć dwie zmienne mają referencję do niej.