[置顶] 欢迎您。今天是2023年03月30日。

Singleton模式也叫单态模式,是由GoF提出的23种设计模式中的一种。Singleton模式是一种对象创建型模式,它为一个类生成唯一的实例对象,并提供一个对该实例的全局访问方法。

本文介绍设计模式中的单态(Singleton)模式的概念,用法,以及实际应用中怎么样使用Singleton模式进行开发。

Singleton的概念

Singleton模式是一种对象创建型模式,使用Singleton模式,可以保证为一个类只生成唯一的实例对象。也就是说,在整个程序空间中,该类只存在一个实例对象。其实,GoF对Singleton模式的定义是:保证一个类只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。

UML类图

为什么要使用Singleton模式呢?

在应用系统开发中,我们常常有以下需求:

  • 在多个线程之间,比如servlet环境,共享同一个资源或者操作同一个对象
  • 在整个程序空间使用全局变量,共享资源
  • 大规模系统中,为了性能的考虑,需要节省对象的创建时间等等

因为Singleton模式可以保证为一个类只生成唯一的实例对象,所以这些情况,Singleton模式就派上用场了。

Singleton模式的实现

Singleton模式是设计模式中相对比较简单的模式之一。理解以及使用方法都比较简单。

Singleton模式有多个实现方法。但目前,每一种都存在或多或少的问题。

下面我们将给出几种实现方法,同时对它们加以比较。

第一种方法:

这是一种最简单的实现方法。但是一种相对有效的实现方法。现在,一般推荐这一种方法作为Singleton模式的实现方法。

/**
 * 单例模式第一种,类定义final放置子类继承
 */
public final class Singleton1 {
  // 自身唯一实例
  private static final Singleton1 instance = new Singleton1();

  /**
   * 防止外部创建新实例
   */
  private Singleton1(){}

  /**
   * 提供唯一实例的的全局访问点
   */
  public static final Singleton1 getInstance() {
    return instance;
  }
};

我们注意到,这种方法没有对instance=newSingleton()部分作同期化操作,但考虑到Singleton实例的生成只是在最初被调用时才执行一次,如果我们在调用时适当处理一下,比如在程序的统一初期化时(SERVLET环境的情况下可以在容器被初始化时如SevletListener里)调用一下Singleton,就不会存在线程安全问题。

第二种方法:

public final class Singleton2 {
  private static final Singleton2 instance;

  private Singleton2(){}

  public static synchronized Singleton2 getInstance() {
    if(instance == null) {
      instance = new Singleton2();
    }
    return instance;
  }
};

该方法把Singleton实例生成放到了getInstance方法里,同时使用synchronized解决了线程安全问题。但如果在高并发的应用系统中,大量的线程在调用getInstance时会受到阻塞,系统的性能将受到严重影响。

第三种方法:

public final class Singleton3 {
  private static final Singleton3 instance;

  private Singleton3(){}

  public static synchronized Singleton3 getInstance() {
    if(instance == null) {
      synchronized(this){   
        if(instance == null){
          instance = new Singleton3();
        }
      }
    }
    return instance;
  }
};

该方法也叫double-check(双重检查)方法,把线程同步synchronized放到只会被执行一次的同步块里。该方法虽然解消了性能瓶颈问题,但该方法被指出并不是线程安全的(不同步的情况下引用类型不是线程安全的)。

第四种方法:

public final class Singleton4 {
  private volatile static Singleton4 instance;

  private Singleton4(){}

  public static synchronized Singleton4 getInstance() {
    if(instance == null) {
      synchronized(this){   
        if(instance == null){
          instance = new Singleton4();
        }
      }
    }
    return instance;
  }
};

该方法在第三种方法的基础上,为Singletoninstance的定义加上volatile关键字修饰,该方法也被称为double-checkvolatile方法。但该方法却依奈不同的编译器。也就是说,在某些编译环境中,第四种方法也是非线程安全的。

您可能也喜欢

GRASP是General Responsibility Assignment Software patterns(通用职责分配软件模式)的简称,它的核心思想是“职责分配(Responsibility Assignment)”。GRASP提出了几个基本原则,用来解决面向对象设计的一些问题。

信息专家模式(Information Expert)是GRASP模式中解决类的职责分配问题的最基本的模式。

创建者模式(Creator)是GRASP模式中解决类的实例的创建职责问题的模式。

二维码
摄像头