在PHP 5.3中创建Singleton基类

时间:2010-10-19 20:48:03

标签: php singleton

直截了当: 我有两个单身人士课程,都是从超级课程继承他们的单身人士。我在第一个单例上初始化了一些属性,然后让第二个单例检索第一个单例的 实例。然而,那个例子似乎并不是我最初初始化的那个例子。一些示例代码可能有助于解释这一点:

首先,超类,提供单身性质(需要PHP 5.3或更高版本):

class Singleton {

    protected static $instance;

    protected function __construct() { }

    final private function __clone() { }

    public static function getInstance() {
        if (!(static::$instance instanceof static)) {
            static::$instance = new static();
        }
        return static::$instance;
    }

}

然后我们得到了第一个带有值的单身人士:

require_once('Singleton.php');

class SingletonA extends Singleton {

    protected $value;

    public function SingletonA() {
        $this->value = false;
    }

    public function getValue() {
        return $this->value;
    }

    public function setValue($value) {
        $this->value = $value;
    }

}

然后引用第一个单例的第二个单例:

require_once('Singleton.php');
require_once('SingletonA.php');

class SingletonB extends Singleton {

    public function getValue() {
        return SingletonA::getInstance()->getValue();
    }

}

现在进行测试,显示失败的原因:

require_once('SingletonA.php');
require_once('SingletonB.php');

SingletonA::getInstance()->setValue(true);

echo (SingletonA::getInstance()->getValue()) ? "true\n" : "false\n";
echo (SingletonB::getInstance()->getValue()) ? "true\n" : "false\n";

测试产生以下输出:

true
false

显然,测试代码引用的SingletonA实例与SingletonB实例引用的实例不同。简而言之,SingletonA并不像我需要的那样单一。这怎么可能?我能用什么魔法来弥补这种行为,给我一个真正的单身人士?

4 个答案:

答案 0 :(得分:11)

尝试使用isset而不是instanceof

class Singleton {
    protected static $instances;

    protected function __construct() { }

    final private function __clone() { }

    public static function getInstance() {
        $class = get_called_class();

        if (!isset(self::$instances[$class])) {
            self::$instances[$class] = new $class;
        }
        return self::$instances[$class];
    }
}

答案 1 :(得分:0)

我很确定这是因为您使用的是非实例化的静态方法。

答案 2 :(得分:0)

SingletonASingletonB是不同的类。虽然它们是从同一个类继承的,但它们是独立的类,因此它们具有不同的静态实例。

如果您更改代码以获得SingletonA的2个实例或SingletonB的2个实例,您将看到您期望的行为。但因为它们是不同的类,它们不是同一个单身。

答案 3 :(得分:0)

我们来谈谈OO。 :)

SingletonASingletonB的类型为Singleton

因此可以说:

  

SingletonA Singleton

     

     

SingletonB Singleton

即。 他们都是Singleton

Singleton的预期含义意味着只能有一个。{使用您的代码的OO背景中的许多人将会感到困惑。

通常,Singleton的实现将基于每个类,因为大多数OO语言都不会倾向于允许您提出的意图。

PHP可能会做(通过get_called_class()魔术)并不意味着应该这样做。

我绝对可以接受,从功利主义的角度来看,接受的答案看起来很好。考虑到已接受答案的优点,我建议更改一个与“标准”Singleton实现不冲突的名称。从严格的OO角度来看,人们永远不会从Singleton继承,所以它确实需要一个不同的名称。