To: Bryan
In this model it is still workable if your singleton variable is actually an array. Consider:
<?php
abstract class Singleton {
protected final static $instances = array();
protected __construct(){}
protected function getInstance() {
$class = get_real_class(); if (!isset(self::$instances[$class])) {
self::$instances[$class] = new $class();
}
return self::$instances[$class];
}
}
class A extends Singleton {
}
class B extends Singleton {
}
$a = A::getInstance();
$b = B::getInstance();
echo "\$a is a " . get_class($a) . "<br />";
echo "\$b is a " . get_class($b) . "<br />";
?>
This would output:
$a is a A
$b is a B
The only alternative as described elsewhere is to make getInstance() protected abstract, accept the class name as an argument, and extend this call with a public final method for every sub-class which uses get_class() in its local object scope and passes it to the superclass.
Or else create a singleton factory like this:
<?php
final class SingletonFactory {
protected static $instances = array();
protected getInstance($class) {
if (!isset(self::$instances[$class])) {
self::$instances[$class] = new $class();
}
return self::$instances[$class];
}
}
?>
The downside to this of course to this latter model is that the class itself doesn't get to decide if it is a singleton, the calling code gets to decide this instead, and a class that really wants or *needs* to be a singleton has no way to enforce this, not even by making its constructor protected.
Basically these design patterns, and various other meta manipulations (things which operate on the nature of the object, not on the data the object holds) could benefit greatly from knowing exactly what the final type of this object is, and not having native access to this information obligates work-arounds.