单例模式最佳实践

项目有个类需要使用单例模式,这我熟悉啊,眨眼之间就写了如下代码

class A
{
    protected static $instance = null;

    public static function getInstance()
    {
        if (is_null(self::$instance)) {
            self::$instance = new self();
        }
       
        return self::$instance;
    }
   
    //todo
}

写完了,可以回家了,不过凭我多年写代码第六感的直觉,我隐约觉得好像哪里不对,瞟了一眼老司机的代码,如下

class A
{
    protected static $instance = null;

    public static function getInstance()
    {
        if (is_null(self::$instance)) {
            self::$instance = new static();
        }
       
        return self::$instance;
    }
   
    public function say()
    {
        echo 'I am A'.PHP_EOL;
    }
}

看似一样,实则暗藏玄机,关键就在new static(),你可能会说这个我知道,后期静态绑定,如果你这么认为,那么我只能说,恭喜你,答对了。如果你不知道这是啥,没关系,请看这里
可是why要这么写呢,我脑海中出现了柯南后脑勺的那道闪电,继承。看下面代码

class A
    {
        protected static $instance = null;
    
        public static function getInstance()
        {
            if (is_null(self::$instance)) {
                self::$instance = new self();
            }
           
            return self::$instance;
        }
       
        public function say()
        {
            echo 'I am A'.PHP_EOL;
        }
    }
   
    class B extends A
    {
        public function say()
        {
            echo 'I am B'.PHP_EOL;
        }
        
        public function test()
        {
            echo 'B test'.PHP_EOL;
        }
        
    }
   
   $b = B::getInstance(); //$b是类A的实例
   $b->test();

运行结果

PHP Fatal error:  Uncaught Error: Call to undefined method A::test()

$b是类A的实例,但是我们需要类B的实例,使用new static()的话,B::getInstance()得到类B的实例,这对应后期静态绑定的非转发调用(non-forwarding call)

在tp和laravel框架中,Container类是这样实现的单例,这种写法我觉得从语义上更清晰一些,但是功能上是一样的。

**
* Set the globally available instance of the container.
*
* @return static
*/
public static function getInstance()
{
    if (is_null(static::$instance)) {
        static::$instance = new static;
    }

    return static::$instance;
}
原文地址:https://www.cnblogs.com/whyly/p/13717178.html