我尝试实现一个能够将参数传递给教师的单例模式。对于单例模式,我想创建一个基类。这个问题的主要问题是并非所有派生类都具有相同数量的参数。对于单身基类,到目前为止我有这个:
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();
}
}
到目前为止,这是有效的,但是我不能用这个将参数传递给构造函数。当然我可以直接将$ args数组传递给构造函数,但我不想在派生类的每个构造函数中展开数组,我希望能够将参数作为普通参数传递。
我已经尝试了几件事:我尝试使用call_user_func_array,但我无法弄清楚如何用这个函数构造一个对象(如果它可能的话),我也尝试使用ReflectionClass。 ReflectionClass的问题是这个类无法访问构造函数,因为构造函数受到保护。
所有人对我有什么想法如何解决这个问题?
PS。对不起,如果我表现得很困难,但我只是想找到最好的解决方案(并了解解决方案)。
答案 0 :(得分:2)
首先,您最好使用静态成员变量。由于您无法动态调用new
,因此您无法使用init
函数。
我将如何做到:
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];
}
}
因此,您的扩展类将使用_init
而不是__construct
:
class foo extends Singleton {
protected function _init($foo) {
$this->foo = $foo;
}
}
请注意,Singleton::__construct
现在是私有的,以防止被误用。
所有这些都不是因为singletons是evil而should是avoided。所以如果你必须使用它们,你可以。但找到一个更好的方法,因为他们真的那么糟糕......
答案 1 :(得分:1)
如果您的意思是在实例中需要一些默认设置,则可以在子设备中设置私有设置数组:
class Simpleton extends Singleton
{
private $settings;
protected function __construct()
{
$this->settings = array(
//default settings here
);
}
}
不要尝试将参数合并到单例中。如果你需要一个参数化的构造函数,不要打扰单例。
单身人士应该有默认值,然后是访问者/变异者,用于调整任何可以调整的设置。