CH05-创建型-单例

模式动机

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

方式是让类自身负责保存它的唯一实例,保证没有其他实例被创建,并且提供一个访问该实例的方法。

模式定义

单例模式(Singleton Pattern),确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。

单例模式的要点有三个:类只能有一个实例;必须自行创建这个实例;必须向整个系统提供这个实例。

模式结构

单例模式仅有一个角色:Singleton

类图

NAME

时序图

NAME

代码实例

模式分析

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

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

  • 单例类的构造函数为私有;
  • 提供一个自身的静态私有成员变量;
  • 提供一个共有的静态工厂方法。

优点

  • 提供了对唯一实例的受控访问。因为单例类封装了它唯一的实例,所以他可以严格控制客户端怎样以及何时访问它,并为设计及开发团队提供了共享的概念。
  • 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,该模式可以提高系统性能。
  • 允许可变数目的实例。可以基于单例模式进行扩展,使用与单例控制相似的方法来获得指定个数的对象实例。

缺点

  • 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。
  • 单例类的职责过重,在一定程度上违背了单一职责原则。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当产品角色,包含一些业务方法,将产品的创建和产品本身的功能融合到了一起。
  • 滥用单例将带来一些负面问题,比如,为了节省资源将数据库连接池对象设计成单例类,可能会导致共享该连接池对象的程序过多而出现连接池溢出;如果该对象长期不使用将被 GC 回收,导致对象状态丢失。

适用场景

  • 系统中只需要一个实例对象,如提供一个序列号生成器,或资源消耗太大而只能创建一个实例。
  • 客户端调用类的单个实例只允许适用一个公共访问点,不能通过其他途径访问该实例。
  • 系统中要求一个类只能有一个实例时才应当使用单例模式。