Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Абстрактный Singleton в php 5.3
 
 автор: Agronom   (02.11.2015 в 11:49)   письмо автору
 
 

В 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];
    }
}



В итоге пришлось создать статический массив в абстрактном классе и хранить там все созданные объекты.

  Ответить  
 
 автор: cheops   (03.11.2015 в 22:08)   письмо автору
 
   для: Agronom   (02.11.2015 в 11:49)
 

Трейты - это то, что у нормальных людей называется миксинами. Зачем их ввели в язык с интерфейсами не понятно... но логично, что до 5.4 для реализации функционала трейтов вы можете использовать интерфейсы (пусть даже не так удобно).

А чем вам статический массив для синглетона не угодил? Самая адекватная реализация... трейты - это вариант для ООП-моделей, где отсутствует множественное наследование, а вам в классы надо намешать чего-то повторяющегося.

  Ответить  
 
 автор: Agronom   (05.11.2015 в 12:12)   письмо автору
 
   для: 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).

  Ответить  
 
 автор: cheops   (07.11.2015 в 10:03)   письмо автору
 
   для: Agronom   (05.11.2015 в 12:12)
 

Ну да, с трейтсами не нужно наследоваться от абстрактного класса с реализацией синглетона, можно просто подмешать его в те классы, где он нужен. Собственно в разных языках это проблема решается по разному - в C++ есть множественное наследование, в Ruby - миксины (трейтсы взяты с них), в Java - интерфейсы (так как ООП PHP стащили с Java - трейтсов долго не было).

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования