设计模式之单例模式

设计模式之单例模式

  单例模式属于创建型设计模式,提供了一种创建对象的最佳方式。

  定义:一个类有且仅有一个实例,并且自行实例化向整个系统提供。

  问题描述:对于系统中的某些类来说,只有一个实例很重要。比如在Windows中的任务管理器,如果不使用机制对窗口对象进行唯一化,将会弹出多个窗口,且窗口内容显示内容完全一致,那么就重复了对象,造成内存资源的浪费,如果窗口内容显示不一致的话,则意味着在某一瞬间系统有多个状态,与实际不符。那么如何保证一个类只有一个实例并且这个实例易于被访问呢?

  解决方案:让类自身负责保存它的唯一实例,它可以保证没有其它实例被创建,且提供一个访问该实例的方法。

  结构图

设计模式之单例模式

  说明:单例类Singleton,提供了一个静态的getSingleton()方法,供系统获取它唯一的实例;有一个私有的构造函数;内部定义自身的一个静态变量,作为外部共享的唯一实例。

  举个栗子,实现单例模式有以下几种方式:

  1. 饿汉模式(一般情况下建议使用)

         设计模式之单例模式

  由于在定义静态变量的时候实例化单例类,因此在类加载的时候就已经创建了单例对象。这里,当类HungrySingleton被加载时,静态变量instance会被初始化,此时类的私有构造函数会被调用,单例类的唯一实例将被创建,所以饿汉式实现单例类将不会出现创建多个单例对象的情况,可确保单例对象的唯一性。

  优点:在类初始化的时候,无论系统是否需要该单例,都会直接创建实例,所以无需考虑多线程访问的问题;

  缺点:不能实现延迟加载,如果实例化比较复杂,则类加载的时间较长,并且不管将来用不用单例对象都始终占据内存,浪费系统资源。

  2. 双重校验锁(在高并发的情况下推荐使用)

         设计模式之单例模式

  这种方式采用双锁机制,在多线程情况下能保持高性能,可在实例域需要延迟初始化时使用。

  3. 登记式/静态内部类(明确要实现lazy loading效果时推荐使用)

         设计模式之单例模式

  在单例类中增加一个静态内部类,在该内部类中创建单例对象,再将该单例对象通过getInstance()方法返回给外部使用。这样既可以实现了延迟加载,又可以保证线程安全,不影响系统性能,在java语言中不失为一种最好的单例模式的实现方式。

  优点:既实现了延迟加载,又保证了线程安全。

  缺点:只适用于静态域的情况。

  优点:会阻止其它对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例;节省内存的开销,尤其是频繁地创建和销毁实例。

  缺点:没有接口,不能继承,单例类只关心内部逻辑,不关心外面怎样来实例化。

  适用场景

  (1)系统只需要一个实例对象,如序列号生成器等;

  (2)当类只有一个实例且调用者只有一个公共的访问点来访问该实例。