Page 1 of 2
Late Static Binding vs Traditional Singleton
Posted: Mon Jan 14, 2013 5:47 pm
by jraede
In PHP 5.3 we were introduced to late static binding, a cool new way to manage class properties at run time. After using this for quite some time I started to think, hey, this could potentially replace the traditional singleton that we've all been using for so long. Instead of using an single object for all class functions, why not just use the class itself, replace "$this->" with "static::", and use late static binding to set all properties dynamically? I thought for sure someone had written about this, but a quick google search only yielded traditional singleton implementations with only the instance being set with late static binding.
So, instead of doing something like this:
We could do something like this:
To test I wrote a simple script with two different classes, which you can see below. Granted, this is a very simple implementation, but the class using no instantiation and only late static binding performed more than 1 second better than the singleton class on each one of my tests. This is pretty significant.
Code: Select all
class Foo {
protected static $var;
public static function set($var) {
static::$var = $var;
}
public static function get() {
return static::$var;
}
}
class Bar {
protected static $_instance;
protected $var;
public static function instance() {
if(!static::$_instance) {
static::$_instance = new static;
}
return static::$_instance;
}
public function set($var) {
$this->var = $var;
}
public function get() {
return $this->var;
}
}
$start = microtime(true);
for($i=0;$i<100000;$i++) {
Bar::instance()->set($i);
$n = Bar::instance()->get($i);
//Foo::set($i);
//$n = Foo::get($i);
}
$end = microtime(true);
echo 'Time: '.($end - $start);
Results were:
Foo: .98975, .97701, .98959, .98653, .99109
Bar: 2.19747, 2.18299, 2.22071, 2.19148, 2.19010
Now you might say, well yeah, there's an extra step in there, the singleton class has to first grab the instance and then do its business. But that is the case in all implementations of these design patterns. With the traditional singleton, there will always be that extra step in accessing the instance before doing anything else.
So my question is, say this is a more complex class that does more than just getting and setting. Now that we can set static class properties at runtime using late static runtime, can you foresee any event in which object instantiation is REQUIRED in order to perform a certain function? In the past, the only reason why I used the traditional singleton design pattern was because I needed to set properties at runtime; now that I can do that for static class properties, I can't see any reason why I would use that design pattern anymore. Also, could the performance difference be mitigated by a more complex class?
Thoughts?
Re: Late Static Binding vs Traditional Singleton
Posted: Mon Jan 14, 2013 6:33 pm
by requinix
That uses neither LSB or the singleton pattern. You've basically written a registry class.
Re: Late Static Binding vs Traditional Singleton
Posted: Mon Jan 14, 2013 6:47 pm
by jraede
Well, regardless of what you want to call it, there is a clear performance difference here, but mostly everything I've seen written on this involves storing the single object (is this not a singleton? whatever) statically on the class, and all other methods are performed on that instantiated object by doing Class::instance()->foo(). I'm asking why is this the norm, and wouldn't it be better to not have to instantiate anything at all and just have everything run statically on the class?
Re: Late Static Binding vs Traditional Singleton
Posted: Mon Jan 14, 2013 8:12 pm
by requinix
You're comparing apples to oranges. Foo is a registry class and Bar is a singleton. You can't compare their performance because they're doing two very different things.
Re: Late Static Binding vs Traditional Singleton
Posted: Mon Jan 14, 2013 9:47 pm
by Christopher
The way you are coding, why not just use globals and functions. You will get better performance and it will at least be clear (and honest) what you are doing. As long as you proceed with your eyes open about the problems of globals -- why not just code procedurally.
Re: Late Static Binding vs Traditional Singleton
Posted: Fri Jan 18, 2013 3:51 pm
by VladSun
*PHP* Singletons and late static bindings are highly coupled

Before PHP 5.3 one had to implement the get-instance (or use ugly workarounds) method in order to have a Singleton class.
Late static bindings *finally* solved this problem.
Let me share my Singleton base class implementation:
Code: Select all
<?php
/**
*
* Singleton pattern base class.
*/
abstract class Singleton {
protected static $_instances = array();
/**
* __construct
* Constructor can't be called directly, thus getInstance()
* is the only way to instantinate the class
*
* @access private
*/
private function __construct() {
}
/**
* __clone
* Singletons can't be cloned
*
* @final
* @access public
* @throws BadMethodCallException
*/
public final function __clone() {
throw new BadMethodCallException('Clone is not allowed.');
}
/**
* __wakeup
* Singletons can't be deserialized
*
* @final
* @access public
* @throws BadMethodCallException
*/
public final function __wakeup() {
throw new BadMethodCallException('Deserializing is not allowed.');
}
/**
* getInstance
* Return the one and only instance of the class
*
*
* @static
* @final
* @access public
* @return Singleton Singleton instance
*/
public static final function getInstance() {
$class = \get_called_class();
if (!isset(static::$_instances[$class])) {
static::$_instances[$class] = new static;
}
return static::$_instances[$class];
}
}
And extending the class:
Code: Select all
class A_Class extends Singleton {
public function echoMyClass() {
echo get_class($this) . PHP_EOL;
}
}
class B_Class extends Singleton {
public function echoMyClass() {
echo get_class($this) . PHP_EOL;
}
}
$a = A_Class::getInstance();
$a->echoMyClass();
$b = B_Class::getInstance();
$b->echoMyClass();
Output:
[text]A_Class
B_Class
[/text]
PS: The one and only purpose of the Singleton pattern is to ensure that there is only one instance of a class. Singletons should not be used as another way for global access. Basically, one should use the getInstance() method in the same way the new operator is used.
Re: Late Static Binding vs Traditional Singleton
Posted: Fri Jan 18, 2013 3:58 pm
by requinix
Vlad, that won't work if you try to use two singleton classes at once.
Code: Select all
class A extends Singleton { }
class B extends Singleton { }
var_dump(A::getInstance());
var_dump(B::getInstance());
Code: Select all
object(A)#1 (0) {
}
object(A)#1 (0) {
}
Re: Late Static Binding vs Traditional Singleton
Posted: Fri Jan 18, 2013 4:11 pm
by VladSun
Correct!
Thanks god, I haven't used singletons so much
I've searched and read again about late bindings ... Found a working implementation of singleton base class - edited my previous post.
Re: Late Static Binding vs Traditional Singleton
Posted: Fri Jan 18, 2013 4:43 pm
by Benjamin
VladSun wrote:PS: The one and only purpose of the Singleton pattern is to ensure that there is only one instance of a class. Singletons should not be used as another way for global access. Basically, one should use the getInstance() method in the same way the new operator is used.
Are you saying that a registry should not be a singleton?
Re: Late Static Binding vs Traditional Singleton
Posted: Fri Jan 18, 2013 5:01 pm
by VladSun
Benjamin wrote:Are you saying that a registry should not be a singleton?
It can be. But IMHO, the registry object (i.e. the getInstance() result ) should be injected into the client object, not accessed within the client object methods by using the getInstance() method.
Re: Late Static Binding vs Traditional Singleton
Posted: Fri Jan 18, 2013 5:54 pm
by Benjamin
I tried engineering a system using the dependency injection methodology and it just didn't feel right, and I also think it made things much more complex if I remember correctly.
Re: Late Static Binding vs Traditional Singleton
Posted: Sat Jan 19, 2013 10:00 am
by Christopher
Benjamin wrote:I tried engineering a system using the dependency injection methodology
Every time you pass an object to the constructor when instantiating an object -- you are doing DI. What exactly did you do as a "dependency injection methodology"?
Benjamin wrote: and it just didn't feel right,
Not feeling right does not necessarily mean not right. Many best practices are counter-intuitive and feel odd initially.
Benjamin wrote: and I also think it made things much more complex if I remember correctly.
Do you remember how it increased complexity. Not using globals always increases "complexity" in that sense.
Re: Late Static Binding vs Traditional Singleton
Posted: Sat Jan 19, 2013 1:27 pm
by Benjamin
I think the issue was that in many cases the dependencies also can have dependencies so you end up having to create new instances of dependencies of dependencies all over. Also all the code has to be written in a way that can handle this, which for the most part is only ever needed for testing because other than that you can typically just extend an interface to get the desired effects.
I understand your "it may feel counter-intuitive" assertion. Where's an example of DI that looks counter intuitive but is the best solution and not written solely so the code can be unit tested?
But... this was years and years ago so I'm not 100% sure these are the issues that turned me off or not.
Off-Topic: I thought you were in CA? Did you move to NY?
Re: Late Static Binding vs Traditional Singleton
Posted: Sat Jan 19, 2013 3:17 pm
by Christopher
Benjamin wrote:I think the issue was that in many cases the dependencies also can have dependencies so you end up having to create new instances of dependencies of dependencies all over. Also all the code has to be written in a way that can handle this, which for the most part is only ever needed for testing because other than that you can typically just extend an interface to get the desired effects.
I understand your "it may feel counter-intuitive" assertion. Where's an example of DI that looks counter intuitive but is the best solution and not written solely so the code can be unit tested?
But... this was years and years ago so I'm not 100% sure these are the issues that turned me off or not.
Yes, you need some automation to do the wiring and injection. A framework or registry can help, as can a DI container. The thing I have found is that though it may be a few more lines of code to instantiate and inject -- it tends to force me to make more reusable code and makes it explicit what is going on.
And don't get me wrong, I don't think dependency injection is a magic bullet to use in every situation. But I have found that for general application-wide wiring that DI works well.
Benjamin wrote:Off-Topic: I thought you were in CA? Did you move to NY?
Not long ago. I'm a notch closer to you lot now!
Re: Late Static Binding vs Traditional Singleton
Posted: Mon Jan 21, 2013 4:23 pm
by VladSun
For me the most important part (specific to Singleton pattern) is:
ClassOfSingleton::getInstance() === new Class()
use the getInstance() method the way you want, just don't abuse it

Keep in mind it's another way of creating objects. Just the way you use Registry or Factory pattern objects.