programing

PHP5에서 Singleton 디자인 패턴 만들기

copysource 2022. 10. 1. 14:49
반응형

PHP5에서 Singleton 디자인 패턴 만들기

PHP5 클래스를 사용하여 Singleton 클래스를 만드는 방법은 무엇입니까?

/**
 * Singleton class
 *
 */
final class UserFactory
{
    private static $inst = null;

    // Prevent cloning and de-serializing
    private function __clone(){}
    private function __wakeup(){}


    /**
     * Call this method to get singleton
     *
     * @return UserFactory
     */
    public static function Instance()
    {
        if ($inst === null) {
            $inst = new UserFactory();
        }
        return $inst;
    }
    
    /**
     * Private ctor so nobody else can instantiate it
     *
     */
    private function __construct()
    {
        
    }
}

사용 방법:

$fact = UserFactory::Instance();
$fact2 = UserFactory::Instance();

$fact == $fact2;

단,

$fact = new UserFactory()

에러를 발생시킵니다.

스태틱 변수 범위와 설정에 대해서는http://http://php.net/manual/en/language.variables.scope.php#language.variables.scope.static 를 참조해 주세요.static $inst = null;

아쉽게도 Inwdr의 답변은 서브클래스가 여러 개 있을 때 끊어집니다.

올바른 상속 가능한 싱글턴 기본 클래스를 다음에 나타냅니다.

class Singleton
{
    private static $instances = array();
    protected function __construct() {}
    protected function __clone() {}
    public function __wakeup()
    {
        throw new Exception("Cannot unserialize singleton");
    }

    public static function getInstance()
    {
        $cls = get_called_class(); // late-static-bound class name
        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";

PHP 5.3에서는 레이트 스태틱바인딩을 통해 상속 가능한 싱글톤 클래스를 만들 수 있습니다.

class Singleton
{
    protected static $instance = null;

    protected function __construct()
    {
        //Thou shalt not construct that which is unconstructable!
    }

    protected function __clone()
    {
        //Me not like clones! Me smash clones!
    }

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

이 문제는 PHP 5.3 이전에 싱글톤을 확장한 클래스가 자신의 클래스가 아닌 부모 클래스의 인스턴스를 생성했다는 점에서 해결되었습니다.

다음 작업을 수행할 수 있습니다.

class Foobar extends Singleton {};
$foo = Foobar::getInstance();

또한 $foo는 싱글톤 인스턴스가 아닌 Foobar 인스턴스가 됩니다.

싱글톤 패턴을 만드는 진정한 현대적 방법은 다음과 같습니다.

<?php

/**
 * Singleton Pattern.
 * 
 * Modern implementation.
 */
class Singleton
{
    /**
     * Call this method to get singleton
     */
    public static function instance()
    {
      static $instance = false;
      if( $instance === false )
      {
        // Late static binding (PHP 5.3+)
        $instance = new static();
      }

      return $instance;
    }

    /**
     * Make constructor private, so nobody can call "new Class".
     */
    private function __construct() {}

    /**
     * Make clone magic method private, so nobody can clone instance.
     */
    private function __clone() {}

    /**
     * Make sleep magic method private, so nobody can serialize instance.
     */
    private function __sleep() {}

    /**
     * Make wakeup magic method private, so nobody can unserialize instance.
     */
    private function __wakeup() {}

}

이제 이렇게 쓸 수 있어요.

<?php

/**
 * Database.
 *
 * Inherited from Singleton, so it's now got singleton behavior.
 */
class Database extends Singleton {

  protected $label;

  /**
   * Example of that singleton is working correctly.
   */
  public function setLabel($label)
  {
    $this->label = $label;
  }

  public function getLabel()
  {
    return $this->label;
  }

}

// create first instance
$database = Database::instance();
$database->setLabel('Abraham');
echo $database->getLabel() . PHP_EOL;

// now try to create other instance as well
$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

보시는 바와 같이 이 인식은 훨씬 더 유연합니다.

인스턴스 복제를 허용하지 않으려면 개인 __clone() 메서드를 추가해야 합니다.

private function __clone() {}

이 메서드를 포함하지 않으면 다음이 가능합니다.

$inst1=UserFactory::Instance(); // to stick with the example provided above
$inst2=clone $inst1;

$inst1!==$inst2 - 같은 경우가 아닙니다.

<?php
/**
 * Singleton patter in php
 **/
trait SingletonTrait {
   protected static $inst = null;

  /**
   * call this method to get instance
   **/
   public static function getInstance(){
      if (static::$inst === null){
         static::$inst = new static();
      }
      return static::$inst;
  }

  /**
   * protected to prevent clonning 
   **/
  protected function __clone(){
  }

  /**
   * protected so no one else can instance it 
   **/
  protected function __construct(){
  }
}

사용 방법:

/**
 *  example of class definitions using SingletonTrait
 */
class DBFactory {
  /**
   * we are adding the trait here 
   **/
   use SingletonTrait;

  /**
   * This class will have a single db connection as an example
   **/
  protected $db;


 /**
  * as an example we will create a PDO connection
  **/
  protected function __construct(){
    $this->db = 
        new PDO('mysql:dbname=foodb;port=3305;host=127.0.0.1','foouser','foopass');
  }
}
class DBFactoryChild extends DBFactory {
  /**
   * we repeating the inst so that it will differentiate it
   * from UserFactory singleton
   **/
   protected static $inst = null;
}


/**
 * example of instanciating the classes
 */
$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를 사용한다면, 그것은 옵션이다. 그래서 당신은 싱글톤 패턴을 갖기 위해 상속 계층을 낭비할 필요가 없다.

또한 다음 코드 행을 추가하지 않을 경우 특성을 사용하거나 싱글턴 클래스를 확장하거나 한쪽 루즈엔드를 사용하는 경우 자녀 클래스의 싱글턴을 만듭니다.

   protected static $inst = null;

아동반에서

예상치 못한 결과는 다음과 같습니다.

object(DBFactoryChild)#1 (0) {
}
object(DBFactoryChild)#1 (0) {
}
protected  static $_instance;

public static function getInstance()
{
    if(is_null(self::$_instance))
    {
        self::$_instance = new self();
    }
    return self::$_instance;
}

이 코드는 클래스 이름에 관계없이 모든 클래스에 적용할 수 있습니다.

클래스당 1줄로 여러 개체를 지원합니다.

이 메서드는 원하는 클래스에 싱글톤을 적용합니다.또한 싱글톤을 만들고 싶은 클래스에1개의 메서드를 추가해야 합니다.이렇게 하면 됩니다.

「에, 「SingleTonBase」를 으로, 오브젝트를 할 수.SingleTonBase★★★★★★★★★★★★★★★★★★.


SingletonBase라는 파일을 만듭니다.php를 스크립트의 루트에 포함합니다.

코드는

abstract class SingletonBase
{
    private static $storage = array();

    public static function Singleton($class)
    {
        if(in_array($class,self::$storage))
        {
            return self::$storage[$class];
        }
        return self::$storage[$class] = new $class();
    }
    public static function storage()
    {
       return self::$storage;
    }
}

싱글톤을 만들고 싶은 클래스에는 이 작은 싱글 메서드를 추가합니다.

public static function Singleton()
{
    return SingletonBase::Singleton(get_class());
}

다음으로 작은 예를 제시하겠습니다.

include 'libraries/SingletonBase.resource.php';

class Database
{
    //Add that singleton function.
    public static function Singleton()
    {
        return SingletonBase::Singleton(get_class());
    }

    public function run()
    {
        echo 'running...';
    }
}

$Database = Database::Singleton();

$Database->run();

이 싱글톤 함수는 가지고 있는 모든 클래스에 추가할 수 있으며 클래스당 인스턴스는 1개만 생성됩니다.

메모: __constructure를 항상 비공개로 하여 새로운 Class(); 인스턴스화를 사용하지 않도록 해야 합니다.

class Database{

        //variable to hold db connection
        private $db;
        //note we used static variable,beacuse an instance cannot be used to refer this
        public static $instance;

        //note constructor is private so that classcannot be instantiated
        private function __construct(){
          //code connect to database  

         }     

         //to prevent loop hole in PHP so that the class cannot be cloned
        private function __clone() {}

        //used static function so that, this can be called from other classes
        public static function getInstance(){

            if( !(self::$instance instanceof self) ){
                self::$instance = new self();           
            }
             return self::$instance;
        }


        public function query($sql){
            //code to run the query
        }

    }


Access the method getInstance using
$db = Singleton::getInstance();
$db->query();

싱글톤 패턴은 반작용으로 간주되기 때문에 굳이 사용할 필요는 없습니다.기본적으로 이 패턴을 전혀 구현하지 않는 데는 많은 이유가 있습니다.이것을 읽고, 「PHP 싱글톤 클래스의 베스트 프랙티스」로 시작해 주세요.

그래도 싱글톤 패턴을 사용할 필요가 있다고 생각되는 경우, 싱글톤 클래스 벤더 추상 클래스를 확장하여 싱글톤 기능을 이용할 수 있는 클래스를 작성할 수 있습니다.

이것이 제가 이 문제를 해결하기 위해 만든 것입니다.

<?php
namespace wl;


/**
 * @author DevWL
 * @dosc allows only one instance for each extending class.
 * it acts a litle bit as registry from the SingletonClassVendor abstract class point of view
 * but it provides a valid singleton behaviour for its children classes
 * Be aware, the singleton pattern is consider to be an anti-pattern
 * mostly because it can be hard to debug and it comes with some limitations.
 * In most cases you do not need to use singleton pattern
 * so take a longer moment to think about it before you use it.
 */
abstract class SingletonClassVendor
{
    /**
     *  holds an single instance of the child class
     *
     *  @var array of objects
     */
    protected static $instance = [];

    /**
     *  @desc provides a single slot to hold an instance interchanble between all child classes.
     *  @return object
     */
    public static final function getInstance(){
        $class = get_called_class(); // or get_class(new static());
        if(!isset(self::$instance[$class]) || !self::$instance[$class] instanceof $class){
            self::$instance[$class] = new static(); // create and instance of child class which extends Singleton super class
            echo "new ". $class . PHP_EOL; // remove this line after testing
            return  self::$instance[$class]; // remove this line after testing
        }
        echo "old ". $class . PHP_EOL; // remove this line after testing
        return static::$instance[$class];
    }

    /**
     * Make constructor abstract to force protected implementation of the __constructor() method, so that nobody can call directly "new Class()".
     */
    abstract protected function __construct();

    /**
     * Make clone magic method private, so nobody can clone instance.
     */
    private function __clone() {}

    /**
     * Make sleep magic method private, so nobody can serialize instance.
     */
    private function __sleep() {}

    /**
     * Make wakeup magic method private, so nobody can unserialize instance.
     */
    private function __wakeup() {}

}

사용 예:

/**
 * EXAMPLE
 */

/**
 *  @example 1 - Database class by extending SingletonClassVendor abstract class becomes fully functional singleton
 *  __constructor must be set to protected becaouse: 
 *   1 to allow instansiation from parent class 
 *   2 to prevent direct instanciation of object with "new" keword.
 *   3 to meet requierments of SingletonClassVendor abstract class
 */
class Database extends SingletonClassVendor
{
    public $type = "SomeClass";
    protected function __construct(){
        echo "DDDDDDDDD". PHP_EOL; // remove this line after testing
    }
}


/**
 *  @example 2 - Config ...
 */
class Config extends SingletonClassVendor
{
    public $name = "Config";
    protected function __construct(){
        echo "CCCCCCCCCC" . PHP_EOL; // remove this line after testing
    }
}

예상대로 동작하고 있는 것을 증명하기 위해서:

/**
 *  TESTING
 */
$bd1 = Database::getInstance(); // new
$bd2 = Database::getInstance(); // old
$bd3 = Config::getInstance(); // new
$bd4 = Config::getInstance(); // old
$bd5 = Config::getInstance(); // old
$bd6 = Database::getInstance(); // old
$bd7 = Database::getInstance(); // old
$bd8 = Config::getInstance(); // old

echo PHP_EOL."COMPARE ALL DATABASE INSTANCES".PHP_EOL;
var_dump($bd1);
echo '$bd1 === $bd2' . ($bd1 === $bd2)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo '$bd2 === $bd6' . ($bd2 === $bd6)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo '$bd6 === $bd7' . ($bd6 === $bd7)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE

echo PHP_EOL;

echo PHP_EOL."COMPARE ALL CONFIG INSTANCES". PHP_EOL;
var_dump($bd3);
echo '$bd3 === $bd4' . ($bd3 === $bd4)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo '$bd4 === $bd5' . ($bd4 === $bd5)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo '$bd5 === $bd8' . ($bd5 === $bd8)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE

이 모든 복잡성("레이트 스태틱바인딩")...harumph)는 단순히 PHP의 파손된 오브젝트/클래스 모델의 표시일 뿐입니다.클래스 객체가 퍼스트 클래스 객체(Python 참조)인 경우 "$_instance"는 클래스 인스턴스 변수입니다. 클래스 객체의 멤버로 인스턴스의 멤버/속성과는 반대로 클래스 객체의 하위 객체에 의해 공유됩니다.Smalltalk 세계에서는 이것이 "클래스 변수"와 "클래스 인스턴스 변수"의 차이입니다.

PHP에서는 패턴이 코드를 작성하기 위한 가이드라는 것을 명심할 필요가 있는 것 같습니다.싱글톤 템플릿을 생각할 수도 있지만 실제 "싱글톤" 클래스에서 상속받은 코드를 작성하려고 하면 PHP에 대해 잘못된 것 같습니다(단, 일부 기업가적인 영혼은 적절한 SVN 키워드를 만들 수 있다고 생각합니다).

공유 템플릿을 사용하여 각 싱글톤을 따로 코딩합니다.

싱글톤-아-악의 논쟁에서 완전히 빠져있다는 걸 알아둬요. 인생은 너무 짧아요

이것이 불필요한 불꽃 전쟁을 일으킬 수 있다는 것은 알지만, 어떻게 여러 데이터베이스 연결을 원하는지 알 수 있습니다. 그러니 싱글톤이 최선의 해결책이 아닐 수도 있다는 점은 인정합니다.하지만 싱글톤 패턴의 다른 용도는 매우 유용하다고 생각합니다.

다음은 예를 제시하겠습니다.저는 정말 가벼운 것을 원했기 때문에 저만의 MVC와 템플링 엔진을 굴리기로 결심했습니다.하지만 내가 표시하고 싶은 데이터에는 and, μ와 같은 특수 수학 문자가 많이 포함되어 있고, 너는...HTML 외에 PDF나 CSV 등의 다른 포맷을 전달할 수 있기 때문에 데이터는 HTML 인코딩이 아닌 실제 UTF-8 문자로 데이터베이스에 저장됩니다.HTML 포맷은 해당 페이지 섹션(니펫) 렌더링을 담당하는 템플릿('보기') 안에 있습니다.적절한 HTML 엔티티로 변환하고 싶은데 PHP get_html_translation_table() 함수는 매우 빠르지 않습니다.데이터를 한 번 검색하여 어레이로 저장하여 모든 사용자가 사용할 수 있도록 하는 것이 좋습니다.여기 속도를 테스트하기 위해 만든 샘플이 있습니다.이는 (인스턴스를 취득한 후) 사용하는 다른 메서드가 스태틱한지 여부에 관계없이 기능합니다.

class EncodeHTMLEntities {

    private static $instance = null;//stores the instance of self
    private $r = null;//array of chars elligalbe for replacement

    private function __clone(){
    }//disable cloning, no reason to clone

    private function __construct()
    {
        $allEntities = get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES);
        $specialEntities = get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES);
        $this->r = array_diff($allEntities, $specialEntities);
    }

    public static function replace($string)
    {
        if(!(self::$instance instanceof self) ){
            self::$instance = new self();
        }
        return strtr($string, self::$instance->r);
    }
}
//test one million encodings of a string
$start = microtime(true);
for($x=0; $x<1000000; $x++){
    $dump = EncodeHTMLEntities::replace("Reference method for diagnosis of CDAD, but clinical usefulness limited due to extended turnaround time (≥96 hrs)");
}
$end = microtime(true);
echo "Run time: ".($end-$start)." seconds using singleton\n";
//now repeat the same without using singleton
$start = microtime(true);
for($x=0; $x<1000000; $x++){
    $allEntities = get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES);
    $specialEntities = get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES);
    $r = array_diff($allEntities, $specialEntities);
    $dump = strtr("Reference method for diagnosis of CDAD, but clinical usefulness limited due to extended turnaround time (≥96 hrs)", $r);
}
$end = microtime(true);
echo "Run time: ".($end-$start)." seconds without using singleton";

기본적으로 다음과 같은 결과를 얻었습니다.

php 테스트.php실행시간: 싱글톤 사용시 27.842966794968초실행시간: 싱글톤 사용시 237.78191494942초

따라서 제가 전문가는 아니지만, 어떤 종류의 데이터에 대한 느린 호출에 따른 오버헤드를 줄이면서 매우 심플하게(필요한 작업을 수행하기 위한 코드 한 줄) 할 수 있는 더 편리하고 신뢰할 수 있는 방법은 없습니다.이 예에서는 유용한 방법이 하나뿐이므로 글로벌하게 정의된 함수보다 나을 것이 없습니다. 그러나 두 가지 방법이 있는 즉시 이 두 가지 방법을 함께 그룹화할 수 있습니다.내 말이 틀렸나?

또한 튜토리얼을 검색할 때 항상 볼 수 있는 "/do useful something here"와 같은 문장이 예제에 포함되어 있는 경우 시각화하기 어려울 수 있기 때문에 실제로 무언가를 수행하는 예를 선호합니다.

어쨌든, 저는 왜 싱글톤을 이런 종류의 일에 사용하는 것이 해로운지(혹은 너무 복잡한지)에 대한 피드백이나 의견을 듣고 싶습니다.

이 기사에서는, 다음의 토픽에 대해 자세하게 설명합니다.http://www.phptherightway.com/pages/Design-Patterns.html#singleton

다음의 점에 주의해 주세요.

  • 컨스트럭터__construct()로서 선언되다protected를 통해 클래스 외부에 새 인스턴스가 생성되지 않도록 하려면new교환입니다.
  • 마법의 방법__clone()로서 선언되다private를 통해 클래스의 인스턴스 복제를 방지하다clone교환입니다.
  • 마법의 방법__wakeup()로서 선언되다private글로벌 함수를 통해 클래스의 인스턴스 직렬화를 방지하다unserialize().
  • 스태틱 작성 방식에서는 레이트 스태틱바인딩을 통해 새로운 인스턴스가 생성됩니다.getInstance()키워드와 함께static이를 통해 의 서브 분류가 가능하게 됩니다.class Singleton를 참조해 주세요.

나는 여기서 공유할 것을 생각하면서 오랫동안 편지를 써왔다.

class SingletonDesignPattern {

    //just for demo there will be only one instance
    private static $instanceCount =0;

    //create the private instance variable
    private static $myInstance=null;

    //make constructor private so no one create object using new Keyword
    private function  __construct(){}

    //no one clone the object
    private function  __clone(){}

    //avoid serialazation
    public function __wakeup(){}

    //ony one way to create  object
    public static  function  getInstance(){

        if(self::$myInstance==null){
            self::$myInstance=new SingletonDesignPattern();
            self::$instanceCount++;
        }
        return self::$myInstance;
    }

    public static function getInstanceCount(){
        return self::$instanceCount;
    }

}

//now lets play with singleton design pattern

$instance = SingletonDesignPattern::getInstance();
$instance = SingletonDesignPattern::getInstance();
$instance = SingletonDesignPattern::getInstance();
$instance = SingletonDesignPattern::getInstance();

echo "number of instances: ".SingletonDesignPattern::getInstanceCount();

첫 번째 답변에는 동의하지만 싱글톤 연장이 싱글톤 패턴에 위반되기 때문에 연장할 수 없도록 최종 수업으로 선언합니다.또한 인스턴스 변수는 직접 액세스할 수 없도록 비공개로 해야 합니다.또한 __clone 메서드를 비공개로 하여 싱글톤 개체를 복제할 수 없도록 합니다.

다음은 코드 예시입니다.

/**
 * Singleton class
 *
 */
final class UserFactory
{
    private static $_instance = null;

    /**
     * Private constructor
     *
     */
    private function __construct() {}

    /**
     * Private clone method
     *
     */
     private function __clone() {}

    /**
     * Call this method to get singleton
     *
     * @return UserFactory
     */
    public static function getInstance()
    {
        if (self::$_instance === null) {
            self::$_instance = new UserFactory();
        }
        return self::$_instance;
    }
}

사용 예

$user_factory = UserFactory::getInstance();

이렇게 하면 (싱글턴 패턴에 위반되는) 작업을 할 수 없게 됩니다.

이럴 순 없어!

$user_factory = UserFactory::$_instance;

class SecondUserFactory extends UserFactory { }

이것이 싱글턴의 올바른 길이어야 한다.

class Singleton {

    private static $instance;
    private $count = 0;

    protected function __construct(){

    }

    public static function singleton(){

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

            self::$instance = new Singleton;

        }

        return self::$instance;

    }

    public function increment()
    {
        return $this->count++;
    }

    protected function __clone(){

    }

    protected function __wakeup(){

    }

} 

특성을 사용하는 @jose-segura 방식은 좋았지만, 하위 클래스에 정적 변수를 정의할 필요는 없었습니다.다음으로 스태틱 로컬 변수의 인스턴스를 클래스 이름으로 인덱싱된 공장 메서드에 캐시함으로써 이를 회피하는 솔루션을 나타냅니다.

<?php
trait Singleton {

  # Single point of entry for creating a new instance. For a given
  # class always returns the same instance.
  public static function instance(){
    static $instances = array();
    $class = get_called_class();
    if( !isset($instances[$class]) ) $instances[$class] = new $class();
    return $instances[$class];
  }

  # Kill traditional methods of creating new instances
  protected function __clone() {}
  protected function __construct() {}
}

사용방법은 @jose-segura와 동일하지만 서브클래스의 스태틱 변수가 필요하지 않습니다.

기존 데이터베이스 인스턴스가 있는지 확인하는 데이터베이스 클래스. 이전 인스턴스를 반환합니다.

   class Database {  
        public static $instance;  
         public static function getInstance(){  
            if(!isset(Database::$instance) ) {  
                Database::$instance = new Database();  
            }  
           return Database::$instance;  
         }  
         private function __cunstruct() {  
           /* private and cant create multiple objects */  
         }  
         public function getQuery(){  
            return "Test Query Data";  
         }  
    }  
    $dbObj = Database::getInstance();  
    $dbObj2 = Database::getInstance();  
    var_dump($dbObj);  
    var_dump($dbObj2);  


/* 
After execution you will get following output: 

object(Database)[1] 
object(Database)[1] 

*/  

참조: http://www.phptechi.com/php-singleton-design-patterns-example.html

다음 예제에서는 데이터베이스 클래스에 싱글톤을 만듭니다.

설계 패턴 1) 싱글톤

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

     return Database::$instance;
    }

  }

  $db=Database::getInstance();
  $db2=Database::getInstance();
  $db3=Database::getInstance();

  var_dump($db);
  var_dump($db2);
  var_dump($db3);

출력은 --

  object(Database)[1]
  object(Database)[1]
  object(Database)[1]

인스턴스 3개가 아닌 단일 인스턴스만 사용

간단한 예:

final class Singleton
{
    private static $instance = null;

    private function __construct(){}

    private function __clone(){}

    private function __wakeup(){}

    public static function get_instance()
    {
        if ( static::$instance === null ) {
            static::$instance = new static();
        }
        return static::$instance;
    }
}

도와줬으면 좋겠다.

위의 답변은 괜찮지만 추가하겠습니다.

2021년에 누가 여기 오든, 제가 또 다른 예를 보여드릴게요.Singletona로서의 패턴 클래스trait모든 수업에서 재사용할 수 있습니다.

<?php

namespace Akash;

trait Singleton
{
    /**
     * Singleton Instance
     *
     * @var Singleton
     */
    private static $instance;

    /**
     * Private Constructor
     *
     * We can't use the constructor to create an instance of the class
     *
     * @return void
     */
    private function __construct()
    {
        // Don't do anything, we don't want to be initialized
    }

    /**
     * Get the singleton instance
     *
     * @return Singleton
     */
    public static function getInstance()
    {
        if (!isset(self::$instance)) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    /**
     * Private clone method to prevent cloning of the instance of the
     * Singleton instance.
     *
     * @return void
     */
    private function __clone()
    {
        // Don't do anything, we don't want to be cloned
    }

    /**
     * Private unserialize method to prevent unserializing of the Singleton
     * instance.
     *
     * @return void
     */
    private function __wakeup()
    {
        // Don't do anything, we don't want to be unserialized
    }
}

그래서 어떤 수업에서도 쉽게 사용할 수 있습니다.예를 들어 싱글턴 패턴을UserSeeder학급.

<?php

class UserSeeder
{
    use Singleton;

    /**
     * Seed Users
     *
     * @return void
     */
    public function seed()
    {
        echo 'Seeding...';
    }
}

다음은 $var = new Singleton()으로 호출할 수 있는 기능과 새 개체를 생성하는지 테스트하기 위한 3가지 변수를 생성하는 예를 보여드리겠습니다.

class Singleton{

    private static $data;

    function __construct(){
        if ($this::$data == null){
            $this->makeSingleton();
        }
        echo "<br/>".$this::$data;
    }

    private function makeSingleton(){
        $this::$data = rand(0, 100);
    }

    public function change($new_val){
        $this::$data = $new_val;
    }

    public function printme(){
        echo "<br/>".$this::$data;
    }

}


$a = new Singleton();
$b = new Singleton();
$c = new Singleton();

$a->change(-2);
$a->printme();
$b->printme();

$d = new Singleton();
$d->printme();

언급URL : https://stackoverflow.com/questions/203336/creating-the-singleton-design-pattern-in-php5

반응형