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.

blog comments powered by Disqus