1、定义
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
2、要点
显然单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。
从具体实现角度来说,就是以下三点:一是单例模式的类只提供私有的构造函数,二是类定义中含有一个该类的静态私有对象,三是该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。
3、优点
3.1、实例控制
单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
3.2、灵活性
因为类控制了实例化过程,所以类可以灵活更改实例化过程。
4、缺点
4.1、开销
虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
4.2、可能的开发混淆
使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用
new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
4.3、对象生存期
不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。
5、PHP
class
test {
private
static
$_instance
;
//保存类实例的私有静态成员变量
//定义一个私有的构造函数,确保单例类不能通过new关键字实例化,只能被其自身实例化
private
final
function
__construct() {
echo
'test __construct'
;
}
//定义私有的__clone()方法,确保单例类不能被复制或克隆
private
function
__clone() {}
public
static
function
getInstance() {
//检测类是否被实例化
if
( ! (self::
$_instance
instanceof
self) ) {
self::
$_instance
=
new
test();
}
return
self::
$_instance
;
}
}
//调用单例类
test::getInstance();
6、应用
单例的应用面很广,可以用在 Cache, Log 等各种资源需要被频繁调用的地方。
比如你有个数据库对象 DB,非单例的做法就是每次用时
$db = new DB();
....
$db->query("....");
用单例,你只需要在工厂方法里判断是否已经初始化过了对象,有就返回,第一次就初始化,程序退出时断开(__destruct),用起来就简单了
$db = DB::getInstance();
$db->query("....");
// 或
$db = DB::getInstance("db2");
$db->insert("xxx", $data);
甚至直接封装成常用函数
DB::query("....");
这样如果你的程序里有很多位于不同层级的地方要使用 DB 对象,只管找 DB 类要就是了,第一次的时候连接,之后都不会重复连接数据库。