简介
场景
系统中,某些类只能有一个实例(例如文件系统管理器、系统计时工具),且需要在系统的任何地方都可以访问到。
这时,可以让类自身以静态属性的方式保存其唯一实例,并私有化构造方法,通过指定的方法获取这个实例。
模式定义
单例模式:确保某个类只有一个实例,而且由这个类负责自身的实例化并保存这个实例。
模式特点
符合单例模式的类有如下特点:
- 只能有一个实例,保存在自身的静态私有成员变量中,通过公有的静态工厂方法获取
- 构造方法私有
- 全局都可以访问这个实例
- 一般延迟初始化,在第一次使用时实例化
优点
- 可以控制客户怎样以及何时访问某个类的实例
- 可以节约系统资源
- 可以基于单例模式进行扩展,获得指定个数的对象实例
缺点
- 单例类扩展困难
- 单例类的职责过重,违背单一职责原则
PHP 代码示例
假设需要对系统中某几种类的实例进行计数,计数类 Counter 采用的就是单例模式:
<?php
class Counter {
private static $instance;
private static $counter = 0;
private function __construct() {
}
public static function getInstance() {
if (empty(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
public function getCounter() {
return self::$counter;
}
public function addCounter() {
self::$counter++;
}
}
class A {
public function __construct() {
$c = Counter::getInstance();
$c->addCounter();
}
}
class B {
public function __construct() {
$c = Counter::getInstance();
$c->addCounter();
}
}
$c = Counter::getInstance();
echo $c->getCounter();
new A();
echo $c->getCounter();
new A();
echo $c->getCounter();
new B();
echo $c->getCounter();
结果是:0123