php单例模式


//单例只允许一个类被实例化一次

//php单例的实现
//单例只允许一个类被实例化一次

class single{
    protected static $ins = null;

    //方法前加final,则方法在继承时不能被修改和覆盖
    //防止继承时修改访问权限
    final protected function __construct(){

    }


    public static function getIns(){
        // if(self::$ins === null){
            self::$ins = new self();
        // }
        return self::$ins;
    }

    //防止被clone
    final protected function __clone(){}

    //这种方式不可行,返回的对象依然是一个新对象
    /*
    public function __clone(){
        return self::$getIns();
    }
    */

}

$a = single::getIns();
$b = single::getIns();
if($a === $b){
    echo 'yes';
}else{
    echo 'no';
}

总结:

1、父类的构造方法定义为protected,无法在外部被直接通过new实例化;

2、使用关键字final后,子类继承后不能修改这个方法的访问属性,就可以禁止子类将构造方法公开。

3、防止clone,可以禁止通过可能产生新的对象。


简单应用:

  写一个简单的数据库单例:

class Db{
    private static $instance;//类实例
    public $handle;//数据库连接对象

    private function __construct($host,$user,$pass,$dbname){
        $connect_result = mysqli_connect($host,$user,$pass,$dbname);
        if (!$connect_result){
              die('Could not connect: ' . mysqli_error());
          }else{
              $this->handle = $connect_result;
              mysqli_set_charset($this->handle,"utf8");
          }
    }

    private function __clone(){

    }

    public static function getDb($host,$user,$pass,$dbname){
        if(!(self::$instance instanceof self)){
            self::$instance = new self($host,$user,$pass,$dbname);
        }
        return self::$instance;
    }

    public function queryData($tableName=''){
        $result = mysqli_query($this->handle,"select * from {$tableName}");
        $arr = array();
        while($row = mysqli_fetch_array($result,MYSQLI_ASSOC)){
            $arr[] = $row;
        }
        // 释放结果集
        mysqli_free_result($result);
        return $arr;
    }

}


$cls = DB::getDb('127.0.0.1','root','123456','exam');
$a = $cls->queryData('user');
var_dump($a);