Как создать класс Singleton с использованием классов PHP5?
Ответ 1
/**
* Singleton class
*
*/
final class UserFactory {
/**
* Вызовите этот метод, чтобы получить синглтон
*
* @return UserFactory
*/
public static function Instance() {
static $inst = null;
if ($inst === null) {
$inst = new UserFactory();
}
return $inst;
}
/**
* Приватный ctor, чтобы никто другой не мог его инстанцировать.
*
*/
private function __construct() {
}
}
Применение:
$fact = UserFactory::Instance();
$fact2 = UserFactory::Instance();
$fact == $fact2;
Но:
$fact = new UserFactory()
Будет выдавать ошибку.
Ответ 2
Вот правильный наследуемый базовый класс Singleton.
class Singleton {
private static $instances = array();
protected function __construct() {}
protected function __clone() {}
public function __wakeup() {
throw new Exception("Невозможно сериализовать синглтон ");
}
public static function getInstance() {
$cls = get_called_class(); // late-static-bound имя класса
if (!isset(self::$instances[$cls])) {
self::$instances[$cls] = new static;
}
return self::$instances[$cls];
}
}
Код теста:
class Foo extends Singleton {}
class Bar extends Singleton {}
echo get_class(Foo::getInstance()) . "\n";
echo get_class(Bar::getInstance()) . "\n";
Ответ 3
PHP 5.3 позволяет создавать наследуемый класс Singleton с помощью позднего статического связывания:
class Singleton {
protected static $instance = null;
protected function __construct() {
// создание через конструктор не допускается!
}
protected function __clone() {
// клонирование также не допускается!
}
public static function getInstance() {
if (!isset(static::$instance)) {
static::$instance = new static;
}
return static::$instance;
}
}
Это решает проблему, заключающуюся в том, что до PHP 5.3 любой класс, расширявший Singleton, создавал экземпляр своего родительского класса вместо своего собственного.
Теперь вы можете:
class Foobar extends Singleton {};
$foo = Foobar::getInstance();
И $ foo будет экземпляром Foobar вместо экземпляра Singleton.
Ответ 4
Настоящий и современный способ сделать шаблон Singleton:
<?php
/**
* Singleton Pattern.
*
* Современная реализация.
*/
class Singleton
/**
* Вызовите этот метод, чтобы получить синглтон
*/
public static function instance() {
static $instance = false;
if( $instance === false ) {
// Позднее статическое связывание (PHP 5.3+)
$instance = new static();
}
return $instance;
}
/**
* Сделайте конструктор приватным, чтобы никто не мог вызвать "new Class".
*/
private function __construct() {}
/**
* Сделать метод clone частным, чтобы никто не мог клонировать экземпляр.
*/
private function __clone() {}
/**
* Сделайте метод sleep magic приватным, чтобы никто не мог сериализовать экземпляр.
*/
private function __sleep() {}
/**
* Сделайте метод wakeup magic приватным, чтобы никто не мог сериализовать экземпляр.
*/
private function __wakeup() {}
}
Так что теперь вы можете использовать это так:
<?php
/**
* Database.
*
* Наследуется от Singleton, поэтому теперь имеет поведение синглтона.
*/
class Database extends Singleton {
protected $label;
/**
* Пример того, что синглтон работает правильно.
*/
public function setLabel($label) {
$this->label = $label;
}
public function getLabel() {
return $this->label;
}
}
// создаем первый экземпляр
$database = Database::instance();
$database->setLabel('Abraham');
echo $database->getLabel() . PHP_EOL;
// теперь попробуйте создать и другой экземпляр
$other_db = Database::instance();
echo $other_db->getLabel() . PHP_EOL; // Abraham
$other_db->setLabel('Priler');
echo $database->getLabel() . PHP_EOL; // Priler
echo $other_db->getLabel() . PHP_EOL; // Priler
Как видите, эта реализация намного более гибкая.
Ответ 5
<?php
/**
* Синглтон паттерн в php
**/
trait SingletonTrait {
protected static $inst = null;
/**
* вызовите этот метод, чтобы получить экземпляр
**/
public static function getInstance(){
if (static::$inst === null){
static::$inst = new static();
}
return static::$inst;
}
/**
* защищена для предотвращения клонирования
**/
protected function __clone(){
}
/**
* защищена, чтобы никто не мог ее использовать
**/
protected function __construct(){
}
}
Применение:
/**
* пример определения класса с использованием SingletonTrait
*/
class DBFactory {
/**
* мы добавляем trait здесь
**/
use SingletonTrait;
/**
* В качестве примера в этом классе будет одно подключение к базе данных.
**/
protected $db;
/**
* В качестве примера мы создадим соединение PDO
**/
protected function __construct(){
$this->db =
new PDO('mysql:dbname=foodb;port=3305;host=127.0.0.1','foouser','foopass');
}
}
class DBFactoryChild extends DBFactory {
/**
* мы повторяем инстанс, чтобы он отличал его.
* от синглтона UserFactory
**/
protected static $inst = null;
}
/**
* пример инстанцирования классов
*/
$uf0 = DBFactoryChild::getInstance();
var_dump($uf0);
$uf1 = DBFactory::getInstance();
var_dump($uf1);
echo $uf0 === $uf1;
Ответ:
object(DBFactoryChild)#1 (0) {
}
object(DBFactory)#2 (0) {
}
Если вы используете PHP 5.4: вам не придется тратить иерархии наследования для того, чтобы иметь шаблон Singleton, а также обратите внимание, что, независимо от того, используете ли вы traits или расширяете класс Singleton, одним свободным методом было создание синглтона дочерних классов, если вы не добавляете следующую строку кода:
protected static $inst = null;
Результат будет:
object(DBFactoryChild)#1 (0) {
}
object(DBFactoryChild)#1 (0) {
}
Web