EasySwoole单例实现原理分析

在前文的分析中发现很多类使用了getInstance()方法获取实例.本篇将对该方法进行刨析

直接跟踪进去

namespace EasySwoole\Component;


trait Singleton
{
    private static $instance;

    static function getInstance(...$args)
    {
        if(!isset(self::$instance)){
            self::$instance = new static(...$args);
        }
        return self::$instance;
    }
}

使用了Trait,专门为了单继承语言而准备的一种代码复用机制.使用方式通过use关键字在类中声明.注意的是Trait不能直接实例化.

下面以框架中CommandRunner类举例.这也是我们框架第一个实例化的类.

use EasySwoole\Component\Singleton;

class CommandRunner
{
    // 引用单例
    use Singleton;
}

use了Trait类相当于复用里面代码,等同于下面这段代码

use EasySwoole\Component\Singleton;

class CommandRunner
{
    // 引用单例
    private static $instance;

    static function getInstance(...$args)
    {
        if(!isset(self::$instance)){
            self::$instance = new static(...$args);
        }
        return self::$instance;
    }
}

关于Trait的更多介绍可以看下 PHP官方文档

这里使用了一个静态方法getInstance 用于获取该类实例化对象.存在直接返回,不存在先实例化保存在self::$instance中再返回

// 判断该类是否实例化过
if(!isset(self::$instance)){
    // 第一次使用时,去实例化对象(延迟实例化,单例模式中的懒汉模式)
    self::$instance = new static(...$args);
}
// 返回该实例
return self::$instance;

需要注意的是这里是通过new static()来实例化,那么它和 new self() 有什么区别呢 下面通过一个简单的Demo解释下,一目了然不用过多解释

class A {
  public static function get_self() {
    return new self();
  }
 
  public static function get_static() {
    return new static();
  }
}
 
class B extends A {}
 
echo get_class(B::get_self()); // A
echo get_class(B::get_static()); // B
echo get_class(A::get_static()); // A

通过static可以实现后期静态绑定(用于在继承范围内引用静态调用的类) 官方文档

另一个区别是 static:: 只能用于静态属性.

关于EasySwoole的单例实现就介绍到此.实现比较简单,像__construct私有化、clone方法拦截也没有处理.毕竟约定大于实现.


Revision #3
Created Mon, Dec 23, 2019 8:01 AM by 小黄
Updated Tue, Jan 7, 2020 1:37 PM by 小黄