Создание базового класса Singleton в PHP 5.3 - PullRequest
10 голосов
/ 20 октября 2010

Прямо в точку: У меня есть два синглтон-класса, оба унаследовали свою синглтон-природу от суперкласса. Я инициализирую некоторые свойства первого синглтона, а затем второй синглтон извлекает экземпляр первого. Этот экземпляр, однако, не похож на тот, который я изначально инициализировал. Некоторый пример кода может помочь объяснить это:

Во-первых, суперкласс, обеспечивающий одноэлементную природу (требуется PHP 5.3 или выше):

class Singleton {

    protected static $instance;

    protected function __construct() { }

    final private function __clone() { }

    public static function getInstance() {
        if (!(static::$instance instanceof static)) {
            static::$instance = new static();
        }
        return static::$instance;
    }

}

Тогда у нас есть первый синглтон со значением:

require_once('Singleton.php');

class SingletonA extends Singleton {

    protected $value;

    public function SingletonA() {
        $this->value = false;
    }

    public function getValue() {
        return $this->value;
    }

    public function setValue($value) {
        $this->value = $value;
    }

}

Затем второй синглтон, который ссылается на первый синглтон:

require_once('Singleton.php');
require_once('SingletonA.php');

class SingletonB extends Singleton {

    public function getValue() {
        return SingletonA::getInstance()->getValue();
    }

}

Теперь для теста, который показывает, как это не удается:

require_once('SingletonA.php');
require_once('SingletonB.php');

SingletonA::getInstance()->setValue(true);

echo (SingletonA::getInstance()->getValue()) ? "true\n" : "false\n";
echo (SingletonB::getInstance()->getValue()) ? "true\n" : "false\n";

Тест дает следующий вывод:

true
false

Ясно, что экземпляр SingletonA, на который ссылается тестовый код, - это не тот экземпляр, на который ссылается экземпляр SingletonB. Короче говоря, SingletonA не так одинок, как мне нужно. Как это возможно? И какую магию я могу использовать, чтобы исправить это поведение, дав мне настоящий синглтон?

Ответы [ 4 ]

11 голосов
/ 20 октября 2010

Попробуйте использовать isset вместо instanceof:

class Singleton {
    protected static $instances;

    protected function __construct() { }

    final private function __clone() { }

    public static function getInstance() {
        $class = get_called_class();

        if (!isset(self::$instances[$class])) {
            self::$instances[$class] = new $class;
        }
        return self::$instances[$class];
    }
}
0 голосов
/ 20 октября 2010

Давай поговорим ОО. :)

SingletonA и SingletonB относятся к типу Singleton

Таким образом, можно сказать:

SingletonA - Singleton

и

SingletonB is Singleton

т.е. они оба Singleton

Ожидаемое значение Singleton означает, что может быть только один. Многие люди из OO-фона, использующие ваш код, будут сбиты с толку.

Как правило, реализация Singleton будет осуществляться отдельно для каждого класса, потому что большинство ОО-языков не будут согнуты, чтобы разрешить намерение того, что вы предлагаете.

То, что PHP может сделать (с помощью get_called_class() magic), не означает, что он должен.

Я могу абсолютно согласиться с тем, что с утилитарной точки зрения принятый ответ выглядит хорошо. Учитывая изящество принятого ответа, я бы предложил изменить имя, которое не противоречит «стандартной» реализации Singleton. С точки зрения строгой OO, никто не может наследовать от Singleton, поэтому ему действительно нужно другое имя.

0 голосов
/ 20 октября 2010

SingletonA и SingletonB - это разные классы. Хотя они наследуются от одного и того же класса, они являются отдельными классами и поэтому имеют разные статические экземпляры.

Если вы измените свой код, чтобы получить 2 экземпляра SingletonA или 2 экземпляра SingletonB, вы увидите ожидаемое поведение. Но поскольку они представляют собой разные классы, они не являются одним и тем же синглтоном.

0 голосов
/ 20 октября 2010

Я уверен, что это потому, что вы используете статические методы, которые не являются экземплярами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...