PHP单例模式使用clone
Posted jfcat
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP单例模式使用clone相关的知识,希望对你有一定的参考价值。
我们来看下php单例模式是否能够clone,先上一段代码。
<?php
class Singleton {
private static $object;
private $name;
private function __construct(string $name) {
$this->name= $name;
}
public static function getInstance(string $name) {
if (self::$object == null) {
$object = new Singleton($name);
}
return $object;
}
}
这是一个单例模式的简单实现,构造函数是private访问修饰符,所以不能直接调用,例如这样new一个会报错:
$c = new Singleton("c");
加上如上代码执行会报错,
~/Develop/PHP/test php singleton.php PHP Fatal error: Uncaught Error: Call to private Singleton::__construct() from invalid context in /Users/mark/Develop/PHP/test/singleton.php:23 Stack trace: #0 {main} thrown in /Users/mark/Develop/PHP/test/singleton.php on line 23
我们通过提供getInstance()静态方法来实现实例化,并保证实例只有一个。如果我们再加上clone会怎么样呢,继续看代码:
$c = new Singleton("c");
$a = Singleton::getInstance("a");
$b = clone $a;
var_dump($a);
var_dump($b);
代码执行的结果是这样的,
object(Singleton)#1 (1) {
["name":"Singleton":private]=>
string(1) "a"
}
object(Singleton)#2 (1) {
["name":"Singleton":private]=>
string(1) "a"
}
对象就是对象,模式只是人为的控制,看下官方对对象复制的描述
对象复制可以通过 clone 关键字来完成(如果可能,这将调用对象的 __clone() 方法)。对象中的 __clone() 方法不能被直接调用。
$copy_of_object = clone $object; 当对象被复制后,PHP 5
会对对象的所有属性执行一个浅复制(shallow copy)。所有的引用属性 仍然会是一个指向原来的变量的引用。__clone(): void 当复制完成时,如果定义了 __clone() 方法,则新创建的对象(复制生成的对象)中的 __clone() 方法会被调用,可用于修改属性的值(如果有必要的话)。
然后我们再增加__clone方法做下实验,
public function __clone() {
$this->name = "clone";
}
再次执行代码,
object(Singleton)#1 (1) {
["name":"Singleton":private]=>
string(1) "a"
}
object(Singleton)#2 (1) {
["name":"Singleton":private]=>
string(5) "clone"
}
返回的结果证明对象clone是成功的,但是这样不符合单例模式的要求,那么如何禁止单例模式下的clone呢,根据php官方的文档,我们知道__clone会在克隆操作完成后被调用,要能够被调用就必须是public访问修饰符,如果改为private,这个方法就不能被调用了,示例如下:
private function __clone() {
$this->name = "clone";
}
再次执行代码,得到以下报错:
PHP Fatal error: Uncaught Error: Call to private Singleton::__clone() from context '' in /Users/mark/Develop/PHP/test/singleton.php:24
Stack trace:
#0 {main}
thrown in /Users/mark/Develop/PHP/test/singleton.php on line 24
证明在调用__clone方法时出错了,这样可以来禁止单例的clone
以上是关于PHP单例模式使用clone的主要内容,如果未能解决你的问题,请参考以下文章