So, I've always implemented a singleton like so:
class Singleton {
private static $_instance = null;
public static function getInstance() {
if (self::$_instance === null) self::$_instance = new Singleton();
return self::$_instance;
}
private function __construct() { }
}
However, it recently struck me that I could also implement it with member-wise static variables:
class Singleton {
public static function getInstance() {
//oops - can't assign expression here!
static $instance = null; // = new Singleton();
if ($instance === null) $instance = new Singleton();
return $instance;
}
private function __construct() { }
}
To me, this is cleaner because it doesn't clutter the class, and I don't have to do any explicit existence check, but because I've never seen this implementation anywhere else, I'm wondering:
Is there anything wrong with using the second implementation over the first?
You probably mean it with a slight modification (I got a syntax error otherwise):
<?php
class Singleton {
public static function getInstance() {
static $instance;
if ($instance === null)
$instance = new Singleton();
xdebug_debug_zval('instance');
return $instance;
}
private function __construct() { }
}
$a = Singleton::getInstance();
xdebug_debug_zval('a');
$b = Singleton::getInstance();
xdebug_debug_zval('b');
This gives:
instance: (refcount=2, is_ref=1), object(Singleton)[1]
a: (refcount=1, is_ref=0), object(Singleton)[1]
instance: (refcount=2, is_ref=1), object(Singleton)[1]
b: (refcount=1, is_ref=0), object(Singleton)[1]
So it has the disadvantage a new zval will be created on each call. This is not particularly serious, so if you prefer it, go ahead.
The reason a zval separation is forced is that inside getInstance
, $instance
is a reference (in the sense of =&
, and it has reference count 2 (one for the symbol inside the method, another for the static storage). Since getInstance
doesn't return by reference, the zval must be separated -- for the return, a new one is created with reference count 1 and the reference flag clear.