记一次单例代码的调整

第一版中我们每个model中都加入单例实现

1
2
3
4
5
6
7
8
9
10
11
12
class A{
public static $obj = false;
public static function instance(){
if(!self::$obj){
self::$obj = new self();
}
return self::$obj;
}
}
A::instance()->....

每个model里面都要写,好麻烦啊,能不能只写一次单例模式?
e

有人说直接把单利模式的实现简单移到父类不就可以了?图样图森破!这里得解释一下,子类中使用父类的静态成员是同一个,所以对个子类的实例会存在覆盖

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
//错误示例
class common{
public static $obj=false;
public static function instance(){
if(!self::$obj){
self::$obj = new static();
}
return self::$obj;
}
}
class a() extends common{
public function say(){
echo 'a';
}
}
class b() extends common{
public function say(){
echo 'b';
}
}
a::instance()->say(); //a
b::instance()->say(); //a 问题出现,父类静态成员obj已经被赋值类a

解决办法

  • 方法1 在父类中存储单例数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class common{
public static $objList = []; //使用容器保存单例对象
public static function instance(){
$class = get_called_class(); //获取静态延迟绑定类的名称
if(!array_key_exists($class,self::$objList)){
self::$objList[$class] = new static(); //使用静态延迟绑定,生成子类对象
}
return self::$objList[$class];
}
}
class A extends common{
}
A::instance()->....
  • 方法2 定义单例trait,每个子类按需添加 这里不再赘述