写了一个单例的基类,其中使用了static::$instance静态变量,看下面代码会出现什么问题:


class Singleton
{
    protected static $instance = null;

    public static function getInstance()
    {

        if (!static::$instance instanceof static) {
            static::$instance = new static();
        }

        return static::$instance;
    }

    function __construct()
    {
        echo '__init__',get_class($this),"\n";
    }
    
    function run()
    {
        echo get_class($this),"\n";
    }
}


class a extends Singleton{}

class b extends Singleton{}

a::getInstance()->run();
a::getInstance()->run();
b::getInstance()->run();
a::getInstance()->run();

结果为:

__init__a
a
a
__init__b
b
__init__a
a

可以看到__init__a出现了2次,这并不是我们想达到的效果,原来静态类变量在继承过程中,是不会自动声明的,改成如下代码解决问题


class a extends Singleton
{
    protected static $instance = null;
}

class b extends Singleton
{
    protected static $instance = null;
}

而这样使用,稍微有些麻烦,容易遗忘,最终的单例基类改成如下:


class Singleton
{
    private static $instance = array();

    public static function getInstance()
    {
        $class = get_called_class();
        if (!isset(self::$instance[$class])) {
            self::$instance[$class] = new static();
        }

        return self::$instance[$class];
    }
}