Web

Создание шаблона проектирования Singleton в PHP5

Как создать класс Singleton с использованием классов PHP5?

 

Ответ 1

/**

 * Singleton class

 *

 */

final class UserFactory {

    /**

     * Вызовите этот метод, чтобы получить синглтон

     *

     * @return UserFactory

     */

    public static function Instance() {

        static $inst = null;

        if ($inst === null) {

            $inst = new UserFactory();

        }

        return $inst;

    }

    /**

     * Приватный ctor, чтобы никто другой не мог его инстанцировать.

     *

     */

    private function __construct() {

 

    }

}

 Применение:

$fact   = UserFactory::Instance();

$fact2 = UserFactory::Instance();

$fact   == $fact2;

Но:

$fact = new UserFactory()

Будет выдавать ошибку.

 

Ответ 2

Вот правильный наследуемый базовый класс Singleton.

class Singleton {

    private static $instances = array();

    protected function __construct() {}

    protected function __clone() {}

    public function __wakeup() {

        throw new Exception("Невозможно сериализовать синглтон ");

    }

    public static function getInstance() {

        $cls = get_called_class(); // late-static-bound имя класса

        if (!isset(self::$instances[$cls])) {

            self::$instances[$cls] = new static;

        }

        return self::$instances[$cls];

    }

}

 Код теста:

class Foo extends Singleton {}

class Bar extends Singleton {}

 

echo get_class(Foo::getInstance()) . "\n";

echo get_class(Bar::getInstance()) . "\n";

 

Ответ 3

PHP 5.3 позволяет создавать наследуемый класс Singleton с помощью позднего статического связывания:

class Singleton {

    protected static $instance = null;

    protected function __construct() {

        // создание через конструктор не допускается!

    }

    protected function __clone() {

        // клонирование также не допускается!

    }

    public static function getInstance() {

        if (!isset(static::$instance)) {

            static::$instance = new static;

        }

        return static::$instance;

    }

}

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

Теперь вы можете:

class Foobar extends Singleton {};

$foo = Foobar::getInstance();

И $ foo будет экземпляром Foobar вместо экземпляра Singleton.

 

Ответ 4

Настоящий и современный способ сделать шаблон Singleton:

<?php

 /**

 * Singleton Pattern.

 * 

 * Современная реализация.

 */

class Singleton 

    /**

     * Вызовите этот метод, чтобы получить синглтон

     */

    public static function instance() {

      static $instance = false;

      if( $instance === false ) {

        // Позднее статическое связывание (PHP 5.3+)

        $instance = new static();

      }

      return $instance;

    }

    /**

     * Сделайте конструктор приватным, чтобы никто не мог вызвать "new Class".

     */

    private function __construct() {}

    /**

     * Сделать метод clone частным, чтобы никто не мог клонировать экземпляр.

     */

    private function __clone() {}

    /**

     * Сделайте метод sleep magic приватным, чтобы никто не мог сериализовать экземпляр.

     */

    private function __sleep() {}

 

    /**

     * Сделайте метод wakeup magic приватным, чтобы никто не мог сериализовать экземпляр.

     */

    private function __wakeup() {}

 

}

Так что теперь вы можете использовать это так:

<?php

 

/**

 * Database.

 *

* Наследуется от Singleton, поэтому теперь имеет поведение синглтона.

 */

class Database extends Singleton {

  protected $label;

  /**

   * Пример того, что синглтон работает правильно.

   */

  public function setLabel($label) {

    $this->label = $label;

  }

  public function getLabel() {

    return $this->label;

  }

}

// создаем первый экземпляр

$database = Database::instance();

$database->setLabel('Abraham');

echo $database->getLabel() . PHP_EOL;

// теперь попробуйте создать и другой экземпляр

$other_db = Database::instance();

echo $other_db->getLabel() . PHP_EOL; // Abraham

$other_db->setLabel('Priler');

echo $database->getLabel() . PHP_EOL; // Priler

echo $other_db->getLabel() . PHP_EOL; // Priler

Как видите, эта реализация намного более гибкая.

 

Ответ 5

<?php

/**

* Синглтон паттерн в php

 **/

trait SingletonTrait {

   protected static $inst = null;

  /**

   * вызовите этот метод, чтобы получить экземпляр

   **/

   public static function getInstance(){

      if (static::$inst === null){

         static::$inst = new static();

      }

      return static::$inst;

  }

  /**

   * защищена для предотвращения клонирования 

   **/

  protected function __clone(){

  }

  /**

   * защищена, чтобы никто не мог ее использовать 

   **/

  protected function __construct(){

  }

}

Применение:

/**

* пример определения класса с использованием SingletonTrait

 */

class DBFactory {

  /**

   * мы добавляем trait здесь 

   **/

   use SingletonTrait;

 

  /**

   * В качестве примера в этом классе будет одно подключение к базе данных.

   **/

  protected $db;

 /**

  * В качестве примера мы создадим соединение PDO

  **/

  protected function __construct(){

    $this->db = 

        new PDO('mysql:dbname=foodb;port=3305;host=127.0.0.1','foouser','foopass');

  }

}

class DBFactoryChild extends DBFactory {

  /**

   * мы повторяем инстанс, чтобы он отличал его.

   * от синглтона UserFactory

   **/

   protected static $inst = null;

}

 

/**

* пример инстанцирования классов

 */

$uf0 = DBFactoryChild::getInstance();

var_dump($uf0);

$uf1 = DBFactory::getInstance();

var_dump($uf1);

echo $uf0 === $uf1;

Ответ:

object(DBFactoryChild)#1 (0) {

}

object(DBFactory)#2 (0) {

}

Если вы используете PHP 5.4: вам не придется тратить иерархии наследования для того, чтобы иметь шаблон Singleton, а также обратите внимание, что, независимо от того, используете ли вы traits или расширяете класс Singleton, одним свободным методом было создание синглтона дочерних классов, если вы не добавляете следующую строку кода:

protected static $inst = null;

Результат будет:

object(DBFactoryChild)#1 (0) {

}

object(DBFactoryChild)#1 (0) {

}

 

Схожие статьи

Web

Получение полного URL-адреса в PHP

Компьютерная сеть 90-х: подробная история развития компьютерных сетей
Web

Компьютерная сеть 90-х: подробная история развития компьютерных сетей

Web

Копируются ли массивы в PHP как значения или как ссылки на новые переменные при передаче в функции

Web

Преобразование форматов даты в PHP

×