Я могу использовать абстрактный класс вместо частного __ конструкция () при создании одиночного элемента в PHP?

При создании Singleton в PHP я удостоверяюсь, что он нельзя инстанцировать путем выполнения следующего:

class Singleton {

    private function __construct() {}
    private function __clone() {}

    public static function getInstance() {}
}

Однако я понял, что, определяя класс, поскольку 'краткий обзор' означает, что нельзя инстанцировать. Так есть ли что-то не так с выполнением следующего вместо этого:

abstract class Singleton {

    public static function getInstance() {}
}

Второй сценарий позволяет мне писать меньше строк кода, которые были бы хороши. (Не то, чтобы это на самом деле имеет большую часть значения.)

6
задан Peter Horne 28 March 2010 в 13:36
поделиться

4 ответа

При создании синглтона в PHP объявление конструкции __ и __ clone как закрытые гарантирует, что класс не может быть инстанциирован извне : он все еще может быть инстанцирован изнутри его объявления.

При объявлении класса как abstract , он вообще не может быть создан ; даже не изнутри его декларации.

Это означает, что ваше решение не будет работать: во втором случае ваш метод getInstance () не сможет создать экземпляр класса, хотя в первом случае он может это сделать.

10
ответ дан 8 December 2019 в 18:34
поделиться

Нет, вы не можете использовать абстрактный класс вместо частного __construct () при создании синглтона. Но если вы намереваетесь создать абстрактный синглтон, из которого можно расширяться, вы можете сделать это следующим образом:

abstract class Singleton
{
   private static $_instances;
   public static function getInstance()
   {
      $className = get_called_class(); // As of PHP 5.3
      if(! isset(self::$_instances[$className] )) {
         self::$_instances[$className] = new $className();
      }
      return self::$_instances[$className];
   }
   protected function __construct( )  {}
   final private function __clone( )  {}
   final private function __wakeup( ) {}
}

Затем вы можете расширить синглтон следующим образом:

class Foo extends Singleton {

    protected $_foo = 1;
    public function setFoo($i) { $this->_foo = $i; }
    public function getFoo() { return $this->_foo; }
}

и

class Bar extends Singleton {

    protected $_foo = 1;
    public function setFoo($i) { $this->_foo = $i; }
    public function getFoo() { return $this->_foo; }
}

и манипулировать:

$foo1 = Foo::getInstance();
$foo1->setFoo(5);

$foo2 = Foo::getInstance();
var_dump($foo2); 

$bar1 = Bar::getInstance();
var_dump($bar1);

echo new ReflectionObject($foo2);
echo new ReflectionObject($bar1);

Однако, имейте в виду, что синглтоны очень сложно тестировать, и их следует по возможности избегать. См. Мой ответ здесь:

1
ответ дан 8 December 2019 в 18:34
поделиться

Нет, потому что тогда вы вообще не сможете создать экземпляр класса (даже в статическом методе getInstance). Частный конструктор в примере синглтона просто гарантирует, что только статический метод getInstance из того же класса может получить доступ к конструктору.

2
ответ дан 8 December 2019 в 18:34
поделиться

Это может сработать, если ваш Singleton::getInstance() должен возвращать экземпляр другого класса.

abstract class Singleton {
  public static function getInstance() {
    static $instance = null;
    if ( is_null($instance) ) {
      $instance = new StdClass; // a different class than 'abstract class Singleton'
      $instance->x = time();
    }
    return $instance;
  }
}

$obj = Singleton::getInstance();

Но я бы счел это запутанным. Немного похоже на неправильное использование abstract для объединения сложности абстрактной фабрики с ограничениями синглтона.

0
ответ дан 8 December 2019 в 18:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: