|
|
|
| В php 5.4 был введен функционал трейтов, с помощью которых можно создать абстрактный функционал для создания singleton.
Но в версии 5.3 это оказалось не так просто. Стандартный подход работать уже не будет:
abstract class Singleton
{
protected static $instance;
private function __construct() {}
public static function getInstance()
{
if (!isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
}
class C extends Singleton
{
}
var_dump(C::getInstance());
|
Так выглядит стандартный подход. В абстрактном контексте мы вместо желаемого попытаемся создать экземпляр абстрактного класса.
Позднее статическое связывание решает проблему, но лишь частично:
abstract class Singleton
{
protected static $instance;
private function __construct() {}
public static function getInstance()
{
if (!isset(static::$instance)) {
static::$instance = new static();
}
return static::$instance;
}
}
class C extends Singleton
{
protected static $instance;
}
var_dump(C::getInstance());
|
Тут нам приходится надеется на присутствие свойства $instance в классе наследнике, что есть плохо и от чего необходимо избавиться. Видимо придется хранить все созданные сингы в абстрактном классе:
abstract class Singleton
{
protected static $instances = array();
private function __construct() {}
public static function getInstance()
{
$calledClass = get_called_class();
if (!isset(self::$instances[$calledClass])) {
self::$instances[$calledClass] = new static();
}
return self::$instances[$calledClass];
}
}
|
В итоге пришлось создать статический массив в абстрактном классе и хранить там все созданные объекты. | |
|
|
|
|
|
|
|
для: Agronom
(02.11.2015 в 11:49)
| | Трейты - это то, что у нормальных людей называется миксинами. Зачем их ввели в язык с интерфейсами не понятно... но логично, что до 5.4 для реализации функционала трейтов вы можете использовать интерфейсы (пусть даже не так удобно).
А чем вам статический массив для синглетона не угодил? Самая адекватная реализация... трейты - это вариант для ООП-моделей, где отсутствует множественное наследование, а вам в классы надо намешать чего-то повторяющегося. | |
|
|
|
|
|
|
|
для: cheops
(03.11.2015 в 22:08)
| | Видимо в PHP 5.3 придется использовать статический массив абстрактного класса.
Но ведь начиная с PHP 5.4 довольно удобно реализовать сингтон:
trait Singleton
{
protected static $instance;
public static function getInstance()
{
if (!isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
}
class A
{
use Singleton;
}
|
Правда тут есть некоторые подводные камни. Мы не можем унаследовать класс от A и использовать его как синглтон:
class C extends A
{
}
var_dump(C::getInstance()); // ВЫВЕДЕТ: class A#1 (0) { ...
|
Поэтому тут тоже не обойтись без статического массива, который будет принадлежать первому классу, что использует трейт (class A). | |
|
|
|
|
|
|
|
для: Agronom
(05.11.2015 в 12:12)
| | Ну да, с трейтсами не нужно наследоваться от абстрактного класса с реализацией синглетона, можно просто подмешать его в те классы, где он нужен. Собственно в разных языках это проблема решается по разному - в C++ есть множественное наследование, в Ruby - миксины (трейтсы взяты с них), в Java - интерфейсы (так как ООП PHP стащили с Java - трейтсов долго не было). | |
|
|
|