PHP 5.3 Абстрактный синглтон-класс и детский? - PullRequest
0 голосов
/ 18 января 2012

у меня есть одноэлементный класс с финальным статическим методом "getInstance ()":

<?php

abstract class Singleton
{
    protected static $instances;

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

        if(!isset(static::$instances[$class]))
            static::$instances[$class] = new $class();

        return static::$instances[$class];
    }
}

И код, подобный этому:

<?php

class C1 extends Singleton { }
class C2 extends Singleton { }

C1::getInstance(); // Created C1 class
C2::getInstance(); // Still get C1 class, get_called_class() return C1 when i try get C2

Что я делаю неправильно?

Ответы [ 6 ]

2 голосов
/ 18 января 2012

Причина, по которой это не работает, заключается в том, что вы не создаете свойство $ instance для каждого из ваших подклассов. Хотя использование static :: и get_called_class () будет обращаться к членам подкласса вместо членов суперкласса, если члены не существуют в подклассе, они будут возвращаться к тем, которые определены в суперклассе. В результате вы все равно получите одного и того же члена.

Попробуйте вместо этого определить свои подклассы.

class C1 extends Singleton { 
    protected static $instances;
}

class C2 extends Singleton { 
    protected static $instances;
}
1 голос
/ 18 января 2012
C1->getInstance();
C2->getInstance();

должно быть

C1::getInstance();
C2::getInstance();

Код

Обновление: Вам не нужен массив для хранения экземпляров, вместо этого пусть подкласс удерживает. Попробуйте код ниже.

class Singleton
{
    private function __construct(){}

    protected static $instance;

    final public static function getInstance()
    {
        $class = get_called_class();
        if(!static::$instance)
            static::$instance = new $class();

        return static::$instance;
    }
}

class C1 extends Singleton { 
    protected static $instance;
}
class C2 extends Singleton {
    protected static $instance;
}

var_dump(C1::getInstance());
var_dump(C2::getInstance());
1 голос
/ 18 января 2012

Попробуйте этот абстрактный Синглтон:

abstract class Singleton
{
    private static $_instances = array();

    public static function getInstance()
    {
        $class = get_called_class();
        if (!isset(self::$_instances[$class])) {
            self::$_instances[$class] = new $class();
        }
        return self::$_instances[$class];
    }
}
0 голосов
/ 30 марта 2015

Нет необходимости переопределять статическое свойство $instance в дочерних классах, просто используйте свойство, определенное в суперклассе:

<?php
class Singleton
{
    public static $Instance;

    private function __construct() { }

    public static function GetInstance() {

        if(!Singleton::$Instance) {
            Singleton::$Instance = new static();
        }
        return Singleton::$Instance;
    }
}

class MyClass extends Singleton
{
    public $field1;
    public $field2;
    public $field3;

    public function __construct()
    {
        $this->field1 = "field1";
        $this->field2 = "field2";
        $this->field3 = "field3";
    }
}

var_dump(Myclass::GetInstance());
?>

Это выводит

object(MyClass)#1 (3) {
  ["field1"]=>
  string(6) "field1"
  ["field2"]=>
  string(6) "field2"
  ["field3"]=>
  string(6) "field3"
}

https://eval.in/306503

0 голосов
/ 06 февраля 2015

Рабочая версия абстрактного синглтона:

abstract class Singletone {
    private static $_instance = NULL;

    private function __construct(){}

    public static function GetInstance() {

        if( !static::$_instance ) {
            static::$_instance = new static();
        }
        return static::$_instance;
    }
}

Производный класс должен перезаписать $ _instance

class DefaultRouter extends Singletone {
    protected static $_instance = NULL;
}
0 голосов
/ 18 января 2012

Я не могу воспроизвести вашу проблему:

var_dump(C1::getInstance());
var_dump(C2::getInstance());

дает:

object(C1)#1 (0) {
}
object(C2)#2 (0) {
}

Как показывает вывод var_dump, типы различаются (C1, затем C2). Помните, что вам нужно вызывать getInstance() статически, так как это статическая функция.

Кроме того, если вы хотите реально реализовать шаблон Singleton в PHP, в вашем абстрактном классе отсутствуют некоторые важные определения методов, чтобы сделать это более точным с помощью PHP. См. Шаблоны & PHP Руководство .

Также в PHP вам, как правило, вообще не нужен Singleton, вместо этого вставляйте зависимости, что сделает ваш код более свободным.

Надеюсь, это полезно.

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