目的:
在整个应用程序的生命周期内(脚本启动到结束),只能拿到单例类的一个对象实例。
比如数据库连接这样的,其他类可以共用一个数据库连接对象实例,不能每次都去new导致连接数递增
实现原理
私有化 __construct
构造函数防止外部调用创建多个实例
私有化 __clone
防止外部克隆
私有化 __wakeup
防止序列化
声明一个 getInstance()
静态方法返回自己的唯一实例
具体代码如下
class Singleton
{
/**
* @var Singleton
*/
private static $instance;
/**
* 通过懒加载获得实例(在第一次使用的时候创建)
*/
public static function getInstance(): Singleton
{
if (null === static::$instance) {
static::$instance = new static();
}
return static::$instance;
}
/**
* 不允许从外部调用以防止创建多个实例
* 要使用单例,必须通过 Singleton::getInstance() 方法获取实例
*/
private function __construct()
{
}
/**
* 防止实例被克隆(这会创建实例的副本)
*/
private function __clone()
{
}
/**
* 防止反序列化(这将创建它的副本)
*/
private function __wakeup()
{
}
}
测试
$singleton1 = Singleton::getInstance();
var_dump($singleton1);
$singleton2 = Singleton::getInstance();
var_dump($singleton2);
$singleton3 = new Singleton();
var_dump($singleton3);
测试结果
object(Singleton)#1 (0) {
}
object(Singleton)#1 (0) {
}
Fatal error: Uncaught Error: Call to private Singleton::__construct() from invalid context in /Users/simon/Code/php/DesignPatternsPHP/Singleton.php:53
Stack trace:
#0 {main}
可以看到$singleton1和$singleton2使用的是同一个对象,而$singleton3去实例化就会报错