关于php单例模式的使用

关键点就是:

  1. 类里面开一个静态变量用于存单例对象
  2. __construct和__clone变成私有方法, 禁止外部访问

先上代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?php


class Demo {
    private static $_instance;

    public $version;

    private function __construct(){
        // self::$_instance = $this;
    }

    private function __clone(){
    }

    public function test($ver = 1){
        $this->version = $ver;
    }

    // $new=true 时将传出一个新的实例
    public static function instance($new = false)
    {
        if ($new) {
            return new self();
        }
        if (empty(self::$_instance)) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
}


// 由于 $this 指向的是当前对象,  self 指向的是类, 因此  self::$_instance = $this; 会将之后的实例给覆盖掉

$ins1 = Demo::instance();
$ins1->test(3);
echo $ins1->version . PHP_EOL;

$ins3 = Demo::instance(true);
$ins3->test();
echo $ins3->version . PHP_EOL;

$ins2 = Demo::instance();
echo $ins2->version . PHP_EOL;

echo $ins2->version . PHP_EOL;

输出:

1
2
3
4
3
1
3
3

由于我当时的画蛇添足, 在构造函数里加了一行 self::$_instance = $this; 导致同样的代码输出却是:

1
2
3
4
3
1
1
1

后来想了想为什么, 回忆一下得出一个答案, 就是 $thisself 的区别

$this 可以说是当前对象的标识符, 注意是对象

self的标识符

对象的区别我认为每个phper都应该知道吧?

回到刚才的问题上, 当我加上 self::$_instance = $this; 时, 代表着把当前对象覆盖到类的静态属性中, 静态属性是和类一起共有同一片内存的, 那么当ins3里新生成对象的时候, 把原有的类属性给覆盖掉了, 因此之后再使用Demo::instance()时获得的对象就和$ins3之前的不一样了

从这里看static这个关键词使用要慎重, 使用场景只有读的情况可以随意使用, 还能节省一点内存(毕竟每个对象查到的属性都是从同一片内存中读的), 但是涉及到 读写 的时候, 就要想明白它的运行顺序了