如何使用PHP5类创建单例类?


当前回答

这应该是Singleton的正确方式。

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(){

    }

} 

其他回答

你可能应该添加一个私有的__clone()方法来禁止克隆实例。

private function __clone() {}

如果您不包含此方法,则可能出现以下情况

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

现在$inst1 !== $inst2 -它们不再是同一个实例了。

我很久以前就写过,想在这里分享

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();
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
/**
 * 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;

respose:

object(DBFactoryChild)#1 (0) {
}
object(DBFactory)#2 (0) {
}

如果你使用的是PHP 5.4: trait,它是一个选项,所以你不必为了拥有单例模式而浪费继承层次结构

还要注意你是使用trait还是扩展Singleton类 如果你不添加以下代码行,就会创建子类的单例:

   protected static $inst = null;

在儿童班

意想不到的结果将是:

object(DBFactoryChild)#1 (0) {
}
object(DBFactoryChild)#1 (0) {
}

所有这些复杂性(“后期静态绑定”……对我来说,harumph)只是PHP对象/类模型破碎的标志。如果类对象是一级对象(参见Python),那么"$_instance"将是一个类实例变量——类对象的成员,而不是其实例的成员/属性,也与它的后代共享相反。在Smalltalk世界中,这就是“类变量”和“类实例变量”之间的区别。

在PHP中,在我看来,我们似乎需要牢记模式是编写代码的指南——我们可能会考虑Singleton模板,但试图编写从实际的“Singleton”类继承的代码对PHP来说是错误的(尽管我认为一些有进取心的人可以创建一个合适的SVN关键字)。

我将继续使用共享模板分别编写每个单例。

请注意,我绝对不会参与单身是邪恶的讨论,生命太短暂了。