单例模式是非常常用的设计模式之一,只需下面几行代码即可生成一个单例模式的对象


class TestService
{
    private static $instance;

    private function __construct(){}
    /** 不容许深度复制 */
    private function __clone() {
    }
    public static function getInstance(){
        if(self::$instance === null){
            self::$instance = new self();
        }
        return self::$instance;
    }
}

$i = TestService::getInstance();

为什么通过上面的代码即获取到的对象是唯一的呢?下面我们逐行分析

  1. 重写__construct()方法,并且改为private类型,这样做得目的是禁止使用new关键字在新建对象,使用new关键字新建的对象是存储在堆上的,而堆有个特点无法共享内存,比如

    $a = new Object()
    $b = new Object()

    以上两行代码,会划分出两块内存,用来存放object对象,即使存放的内容完全一样

  2. 定义一个static类型的变量$instance, 不管任何语言,变量的生命周期都是有限的。以C语言为例,变量是指分配在函数内部的一种数据,它存储在栈上,其声明周期从函数执行时开始,至函数返回时而终,函数执行完后局部变量就从栈上释放了,下次执行时再重新分配、初始化。也就是说,局部变量的值不会保留到下次调用,这是变量的基本属性。 PHP的变量也具有这个属性,虽然并没有像C语言那样直接分配在栈上,但是Zend虚拟机在实际的计算机之上模拟、抽象了一个执行栈:PHP代码执行时由Zend虚拟机分配一块内存,用于记录执行位置、分配局部变量以及调用上下文等,每次函数调用都会重新分配。因此从Zend的角度看,PHP变量的实现与C并没有差别,只不过Zend是更高层次的虚拟机,并不是实际的计算机。

静态变量的特殊之处在于:函数调用返回之时并不会释放,它的结果会被保留到下次函数的调用,其生命周期比局部变量要长。例如:

function my_func(){
    static $count = 4;
    $count++;
    echo $count,”\n”;
}
my_func(); //输出5
my_func(); //输出6

PHP的静态变量存储在一张hash表中,静态变量只会初始化一次,而且是在编译阶段初始化,而不是执行阶段。