面向对象编程中有这种情况,希望类只有一个实例且够成其他类的成员属性,这样如果直接作为全局变量在页面的前面定义类的实例,在其他类中当属性使用,这中做法破坏了oop的封装性,并且如果使用不当会导致命名冲突。而单例模式的设计就是专门为了解决这类问题的。
顾名思义单例就是单个实例,那么这个类必须有一定的规范:构造方法私有 静态私有属性(本类的实例) 公开的静态方法(该方法为了判断该实例是否存在,如果不在则创建。然后返回该实例)。
另外,需要创建__clone()方法防止对象被复制(克隆)
第一种方法:设置魔术方法__clone();访问权限为private
第二种方法:若__clone()为公用方法,则在函数中加上自定义错误,如trigger_error('Clone is not allow!',E_USER_ERROR);
为什么要使用PHP单例模式?
1、php的应用主要在于数据库应用, 所以一个应用中会存在大量的数据库操作, 使用单例模式, 则可以避免大量的new 操作消耗的资源。
2、如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。
3、在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。
在PHP中,所有的变量无论是全局变量还是类的静态成员,都是页面级的,每次页面被执行时,都会重新建立新的对象,都会在页面执行完毕后被清空,这样似乎PHP单例模式就没有什么意义了,所以PHP单例模式我觉得只是针对单次页面级请求时出现多个应用场景并需要共享同一对象资源时是非常有意义的。
example:
class mysqlink {private $host;
private $user;
private $pwd;
private $db;
private $charset;
private $mysqli;
static private $instance;
static public function getInstance(){
if(empty(self::$instance)){
$host = "localhost";
$user = "root";
$DBpwd = "911004";
$db = "box";
$charset = "gbk";
self::$instance=new mysqlink($host, $user, $DBpwd, $db, $charset);
}
return self::$instance;
}
private function __clone(){//限制单例模式的克隆
}
private function __construct($host, $user, $pwd, $db, $charset) {
$this->host = $host;
$this->user = $user;
$this->pwd = $pwd;
$this->db = $db;
$this->charset = $charset;
$this->mysqli = new mysqli("$host", "$user", "$pwd", "$this->db");
if (mysqli_connect_error()) {
die('Connect Error (' . mysqli_connect_errno . ') ' . mysqli_connect_error);
}
if (!$this->mysqli->set_charset($this->charset)) { //设置客户端编码
printf("Error loading character set $this->charset: %s\n", $this->mysqli->error);
}
}
}