设计模式之单例模式

设计模式中最简单的酒是单例模式,单例模式的目的是为了保证在一个进程中,某一类只有一个实例存在。如何保证一个类只有一个示例并且这个实例又能易于被访问呢?定义一个全局变量可以确保对象随时都可以被访问,但不能防止我们实例化多个对象。

其中一个更好的解决办法是让类自身负责保存它的唯一示例。这个类可以保证没有其他实例被创建,并且它可以提供一个访问该实例的方法。

单例模式的要点有三个,一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。单例模式是一种对象创建型模式。单例模式又名单件模式或单态模式。

什么是单例模式

单例模式:也叫单子模式,是一种常用的软件设计模式,属于创建型模式的一种。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。 —— 节选自维基百科

对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或id生成器。

单例模式优缺点

单例模式的目的是保证一个类仅有一个实例,并提供一个访问它的全局访问点。单例模式包含的角色只有一个,就是单例类——Singleton。单例类拥有一个私有构造函数,确保用户无法通过new`关键字直接实例化它。除此之外,该模式中包含一个静态私有成员变量与静态公有的工厂方法,该工厂方法负责检验实例的存在性并实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。

在单例模式的实现过程中,需要注意如下三点:

  1. 单例类的构造函数为私有
  2. 提供一个自身的静态私有成员变量
  3. 提供一个公有的静态工厂方法
优点
  1. 提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它,并为设计及开发团队提供了共享的概念。
  2. 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能。
  3. 允许可变数目的实例。我们可以基于单例模式进行扩展,使用与单例控制相似的方法来获得指定个数的对象实例。
缺点
  1. 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。
  2. 单例类的职责过重,在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。
  3. 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出,如果实例化的对象长时间不被利用,系统会认为它是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致对象状态的丢失。

示例

单例模式主要包含一个类:

单例类:声明了一个名为getInstance方法,用来获取示例的静态方法来返回其所属类的一个相同的示例。单例的构造函数必须对客户端代码隐藏。调用getInstance方法必须是获取单例对象的唯一方式。

类图如下所示:

设计模式之单例模式_第1张图片

代码示例:

//  方法1
class Singleton1 {
    private static instance : Singleton1 = new Singleton1();

    public static getInstance() : Singleton1 {
        return this.instance;
    }
};
console.log(Singleton1.getInstance(), '11111');

//  方法2
class Singleton2 {
    private static instance: Singleton2 = null;

    public static getInstance() : Singleton2 {
        if (this.instance === null) {
            this.instance = new Singleton2();
        }

        return this.instance;
    }
};
console.log(Singleton2.getInstance(), '2222');

//  方法3
class Singleton3 {
    private constructor(){
        this.instance = null;
    }

    public static getInstance() : Singleton3 {
        if (this.instance === null) {
            this.instance = new Singleton3();
        }
        return this.instance;
    }
};
console.log(Singleton3.getInstance(), '3333');

//  方法4
class Singleton4 {
    static instance:Singleton4;

    private constructor():Singleton4{
        if (Singleton4.instance === undefined) {
          Singleton4.instance = this;
        }
        return Singleton4.instance;
    }

};
console.log(Singleton4.getInstance(), '4444');

总结

单例模式作为众多设计模式中最简单的一个设计模式,为了保证某个类只存在一个实例,这个类称为单例类,它提供全局访问的方法。在单例类的内部实现只生成一个实例,同时它提供一个静态的工厂方法,让客户可以使用它的唯一实例;为了防止在外部对其实例化,将其构造函数设计为私有。

你可能感兴趣的