名词解释
单例模式是一种对象创建模式,确保一个类只有一个实力,并且自行实例化向整个系统提供。百度百科对单例模式是这样定义的:
数学与逻辑学中,singleton定义为“有且仅有一个元素的集合”。
单例模式最初的定义出现于《设计模式》(艾迪生维斯理, 1994):“保证一个类仅有一个实例,并提供一个访问它的全局访问点。”
Java中单例模式定义:“一个类有且仅有一个实例,并且自行实例化向整个系统提供。
从定义里不难看出单利模式有三个要点:
1,一个类只有一个实,例。
2,类自身维护自己的实例化(不能在类外用 new关键字实例化)
3,可被系统中的任何对象使用,且不能被存储在会被覆写的全局变量中(在PHP中使用全局会带来很多问题,很多开发团队都是禁止使用的)
为什么要使用单例模式
首先,我们通常把“全局变量是不好的”当做信条。单例对象不能被覆盖,可以弥补全局变量的缺陷。
其次,我们在开发中有时候会希望某个类只能有一个实例。例如数据库连接,通常在一个系统中有大量的数据库操作,如使用单例,每次操作都需要用到new关键字,会消耗大量内存和系统资源,并且频繁对数据库进行打开/关闭连接的操作是对数据库的一种极大的浪费。
实现
第一步:一个类只有一个实例,不能在外部使用new,所以要对构造方法进行重写并封装成类私有的。
第二部:类自身维护自己实例提供被系统中的其他类使用,所以要在类中定义一个公有的静态方法和一个静态私有属性,用以实例化自身,保存自身的唯一实例,并向外界提供自身的唯一实例。
第三部:如果类被继承后,重写构造方法并且封装为Public怎么办?所以需要对构造方法用final进一步修饰。
第四部:如果客户端获取类的实例后使用clone怎么办?所以需要对克隆方法进行重写并封装成私有的。
简单的单例例子
<?php
class SingleDb{
/**
*静态属性$instance保存自身唯一实例
*静态方法getInstance维护自身实例
*/
private $conn;
private static $instance=null;
final private function __construct(){
$this->conn=@new mysqli('localhost','root','root','test');
if(mysqli_connect_errno()){
throw new Exception("连接失败!", 1);
}
$this->conn->set_charset('utf8');
}
/**
*克隆方法重写
*/
private function __clone(){
}
public static function getInstance(){
if(self::$instance==null){
self::$instance=new self();
}
return self::$instance;
}
/**
*查询方法
*
*/
public function select($sql){
$result=array();
$res=$this->conn->query($sql);
if($res){
while ($row = $res->fetch_object()){
$result[] = $row;
}
}
return $result;
}
//其他方法.....
/**
*关闭链接
*/
function __destruct(){
$this->conn->close();
}
}
//客户端测试
$db=new SingleDb();//系统会报错
$db=SingleDb::getInstance();
var_dump($db->select("select * from vgoods"));