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

Автоматическая смена картинок на CSS. Смена изображений по таймеру

Web

Заголовки запросов Cross-Origin (CORS) с заголовками PHP

Что такое видеохостинги типа Ютуба, как на них можно загружать видео
Web

Что такое видеохостинги типа Ютуба, как на них можно загружать видео

Web

Может ли PHP, используя cURL, получить заголовки и тело ответа за один запрос

×