Extending Singletons
This morning, I was wondering about how to extend a singleton class such that
you could retrieve the new class when retrieving the singleton later. In
particular, Zend_Controller_Front
is a singleton, but what if I want to
extend it later? A number of plugins in the Zend Framework, particularly view
helpers and routing functionality, make use of the singleton; would I need to
alter all of these later so I could make use of the new subclass?
For instance, try the following code:
class My_Controller_Front extends Zend_Controller_Front
{}
$front = My_Controller_Front::getInstance();
You'll get an instance of Zend_Controller_Front
. But if you do the following:
class My_Controller_Front extends Zend_Controller_Front
{
protected static $_instance;
public static function getInstance()
{
if (null === self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
}
$front = My_Controller_Front::getInstance();
You'll now get an instance of My_Controller_Front
. However, since
$_instance
is private in Zend_Controller_Front
, calling
Zend_Controller_Front::getInstance()
will still return a
Zend_Controller_Front
instance — not good.
However, if I redefine Zend_Controller_Front::$_instance
as protected, and
have the following:
class My_Controller_Front extends Zend_Controller_Front
{
public static function getInstance()
{
if (null === self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
}
$front = My_Controller_Front::getInstance();
Then the any time I call getInstance()
on either My_Controller_Front
or
Zend_Controller_Front
, I get a My_Controller_Front
instance!
So, the takeaway is: if you think a singleton object could ever benefit from extension, define the static property holding the instance as protected, and then, in any extending class, override the method retrieving the instance.