定义

单例模式(Singleton pattern):一个类有且仅有一个实例,并且自行实例化后提供给整个程序使用。

或者可以理解为在整个程序运行期间,保证这个类有且仅一个实例,并对外提供一个能够访问它的全局访问点。

应用场景

对于一个程序来说,某些特殊的类在程序运行期间仅仅保证只被实例化一次很重要。打印服务是单例模式出镜率比较高的一个例子,对于打印机同一时刻只能打印一个文件,因此出现两个打印服务实例的时候,肯定有一个是处于闲置状态浪费资源,如果没有闲置,那么就会发生资源争夺情况,你肯定不会希望一页纸上交替打印了两个文档吧。

当你打算实现一个框架的时候,如果你是这么思考的,我要先写一个核心,其它的诸如框架配置、控制器、视图、类库等等都和这个核心有关联,这个核心从一接到请求就开始运行,一直到请求结束,所有的其它的组件都由核心来实例化,这个核心就像一个树干一样,其它的组件都像一条条树枝挂在主干上,那么这个核心类最好用单例模式,这时候你所加载的配置,你所实例化的各个组件,在本次运行期间就很确定的是由这一个核心实例化出来的(因为没有别的啦),那么不论你怎么玩也就不会发生 A 实例下的配置信息被 B 实例调用了。

总之,我认为单例模式有最重要的两点,保证唯一以及节省资源。

实现方法

  1. 把构造方法用 private 方式隐藏起来,可以防止被其它类 new 出来。

  2. 没了构造方法了,那么其它类不能 new 出来这个类了,那么只能自食其力自己 new 自己了,然而有个问题,此时自己是不存在的啊,不存在又怎么运行自己 new 自己的方法呢?

  3. 因此要使用静态方法,静态方法可以使用类直接调用,在静态方法中 new 自己,因为是在类里,所以可以无视 private 。

  4. 虽然 new 出来了,但是不保存起来的话,下次再需要时,不是还需要 new 一次 ,那么也就不是单例了,因此要找个安全的地方存起来,而静态方法只能访问静态的属性,因此把 new 出来的对象放到静态属性里吧。

class Singleton {
    private static $_instance;//保存实例化出来的单例
    //构造函数私有化,确保单例类不能通过其它对象 new 出来
    private final function __construct() {}
    //定义私有的__clone()方法,这是确保单例类不能被复制或克隆,否则又不是单例了。
    private function __clone() {}
    public static function getInstance() {
        //检测类是否被实例化,如果没有实例化,就 new 一下,已经实例化就直接返回。
        if ( ! (self::$_instance instanceof self) ) {
            self::$_instance = new test();
        }
        return self::$_instance;
    }
}

//拿到单例实例,多次调用都是同一个实例
Singleton::getInstance();

优点

  1. 提供了对唯一实例达到受控访问。

  2. 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能。

缺点

  1. 单例模式破坏了常见的类模式以及没有抽象层,因扩展时有很大的困难。

  2. 单例模式为了能够保持运行期间唯一并能够被全局访问,污染了全局变量。


sheld
652 声望33 粉丝

我是什么都不知道啊