使用 Traits 實現 Singleton
免責宣告 : 這個例子絕不提倡使用單例。單例需要經常使用。
在 PHP 中,有一種實現單例的標準方法:
public class Singleton {
private $instance;
private function __construct() { };
public function getInstance() {
if (!self::$instance) {
// new self() is 'basically' equivalent to new Singleton()
self::$instance = new self();
}
return self::$instance;
}
// Prevent cloning of the instance
protected function __clone() { }
// Prevent serialization of the instance
protected function __sleep() { }
// Prevent deserialization of the instance
protected function __wakeup() { }
}
為防止程式碼重複,最好將此行為提取到特徵中。
trait SingletonTrait {
private $instance;
protected function __construct() { };
public function getInstance() {
if (!self::$instance) {
// new self() will refer to the class that uses the trait
self::$instance = new self();
}
return self::$instance;
}
protected function __clone() { }
protected function __sleep() { }
protected function __wakeup() { }
}
現在任何想要作為單例運作的類都可以簡單地使用這個特徵:
class MyClass {
use SingletonTrait;
}
// Error! Constructor is not publicly accessible
$myClass = new MyClass();
$myClass = MyClass::getInstance();
// All calls below will fail due to method visibility
$myClassCopy = clone $myClass; // Error!
$serializedMyClass = serialize($myClass); // Error!
$myClass = deserialize($serializedMyclass); // Error!
即使現在不可能序列化單例,但仍然有用的是禁止反序列化方法。