开发者

PHP unfold array singleton constructor

I try to implement a singleton pattern with the capability of passing arguments to the instructor. For the singleton pattern I want to create a base class. The main problem with this is that not all derived classes have the same amount of parameters. For the singleton base class I have this so far:

abstract class Singleton
{
    /**
     * Function: __construct
     * Description: the function which creates the object.
     */
    protected function __construct()
    {

    }
    private final function __clone()
    {
    }
    public static function getInstance()
    {
        $args = func_get_args();
        static $instance = null;

        return $instance = $instance ?  : new static();
    }
}    

So far, this works, but I can't pass arguments to the constructor with this. Of course I can directly pass the $args array to the constructor, but I don't want to have to unfold the array in each constructor of the derived classes, I want to be able to pass the arguments as normal parameters.

I've tried several things already: I tried using call_user_func_array, but I couldn't figure out how to construct an object with this function (i开发者_如何学运维f it's possible at all), and I've also tried using the ReflectionClass. The problem with the ReflectionClass was that this class can't access the constructor since the constructor is protected.

So does anyone has any ideas for me how to solve this?

ps. sorry if I'm acting difficult, but I just try to find the best solution (and understand that solution).


First off, you'd be better to use a static member variable. And since you can't dynamically call new, you're stuck using an init function.

How I would do it is:

abstract class Singleton
{
    protected static $instances = array();
    /**
     * Function: __construct
     * Description: the function which creates the object.
     */
    private function __construct()
    {
    }
    private final function __clone()
    {
    }

    protected abstract function _init();

    public static function getInstance()
    {
        $args = func_get_args();
        $class = strtolower(get_called_class());
        if (!isset(self::$instances[$class])) {
            self::$instances[$class] = new $class();
            call_user_func_array(
                array(
                    self::$instances[$class],
                    '_init'
                ),
                $args
            );
        }
        return self::$instances[$class];
    }
}

So, your extending class would use _init instead of __construct:

class foo extends Singleton {
    protected function _init($foo) {
        $this->foo = $foo;
    }
}

Notice that Singleton::__construct is now private to prevent being mis-used.

All this is not withstanding the fact that singletons are evil and should be avoided. So if you must use them, you can. But find a better way, since they really are that bad...


If you mean that you want some default settings in your instance, you can just set up a private settings array in the child:

class Simpleton extends Singleton
{
  private $settings;

  protected function __construct()
  {
    $this->settings = array(
      //default settings here
    );
  }
}

Don't try to incorporate parameters into a singleton. If you need a parametrized constructor, don't bother with a singleton.

The singleton should have default values, and then accessors/mutators for adjusting whichever settings should be adjustable.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜