设计模式历险记之单例模式

单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

我们先来看看它的结构图:

这个结构图比前几次介绍的结构图简单多了,它只有一个单例类。该类有一个私有的静态属性,是存放该类的实例的;它的构造方法是私有的,所以不能在类的外部去实例化它;它有一个公共的静态方法,是用来获取单例类仅有的这个实例的。

我们再来看看它的代码实现:

<?php
class Singleton{

    //存放唯一实体的属性
    private static $instance;

    //私有的构造方法,使单例类不能再类的外部被实例化
    private function __construct(){}

    //获取唯一实体
    public static function getInstance(){
        if(empty(self::$instance)){
                self::$instance = new self();
        }

        return self::$instance;
    }
    
    //防止clone 多个实例
    private function __clone(){}

    
    //防止反序列化
    private function __wakeup(){}
}

$singletonA = Singleton::getInstance();

$singletonB = Singleton::getInstance();

var_dump($singletonA,$singletonB);

我们仔细阅读上面代码。

我们发现类的构造函数是私有的,说明了该类不能在类外部通过关键字 new 去实例化它,那么我们应该怎样去实例化它呢?

再看代码,发现存放唯一实体的属性和获得这个唯一实体的方法都是静态的,什么是静态的呢,就是当计算机加载到这块代码时候,这块代码就被加载到内存可以供其它代码调用,我们将目光移到 getInstance 这个方法中。

该方法先检查了 instance 属性是不是为空,如果是为空,则在类内部去实例化它,然后返回。如果 instance 属性不是为空的话,则直接返回该属性。

我们接着再看看 instance 这个属性,因为她是静态的,所以只要程序在运行,那么它就会一直存在与内存中,所以,我们一旦将类实例化并赋值给它,那么这个实例化的类就将一直存在于内存,这个时候,从内存中获取这个静态变量始终都是相同的。

我们运行它可以看到:

$singletonA 和 $singleTonB 是两个一模一样的对象,这也印证了上面的分析。

上面只是单例模式的一种形式,叫做 懒汉式单例模式 ,这种单例模式可能会在多线程模式下出现不同的实体。这里具体怎样产生我们后面有机会讨论。

下面我们讨论单例模式的另外一种形式 饥汉式单例模式(特别注意,因为php的部分原因,在php中不能使用饥汉式单例模式,这里只是说明有这种思路)

<?php
class Singleton{

    //注意,这种写法在php中是错误的,这里只是说明有这种思想。
    //加载静态属性的时候实例化对象这种思想
    private static $instance = new self();

    //私有的构造方法,使单例类不能再类的外部被实例化
    private function __construct(){}

    //获取唯一实体
    public static function getInstance(){

        return self::$instance;
    }
}

我自己总结的应用场景:

  • 用于多次实例化相同的类这种场景,把多次实例化相同的类用单例模式来改写后能增加代码的效率。

Snail's Blog
请先登录后发表评论
  • 最新评论
  • 总共0条评论
  • 本博客使用免费开源的 laravel-bjyblog v5.5.1.3 -develop 搭建 © 2014-2018 www.snail-c.cn 版权所有 ICP证:蜀ICP备18023253号-1
  • 联系邮箱:459921737@qq.com