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?
While a static class allows only static methods and and you cannot pass static class as parameter. A Singleton can implement interfaces, inherit from other classes and allow inheritance. While a static class cannot inherit their instance members. So Singleton is more flexible than static classes and can maintain state.
The static keyword is used to declare properties and methods of a class as static. Static properties and methods can be used without creating an instance of the class. The static keyword is also used to declare variables in a function which keep their value after the function has ended.
Singletons may or may not have state and they refer to objects. If they are not keeping state and only used for global access, then static is better as these methods will be faster. But if you want to utilize objects and OOP concepts (Inheritance polymorphism), then singleton is better.
Make a construct method private to make a class Singleton. If you don't want to instantiate a multiple copies of class but only one then you just put it in singleton pattern and you can just call methods of that class and that class will have only one copy of it in a memory even if you create another instance of it.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With