1、简介

所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(这种方法一般是静态的)

2、单例模式八种方式

  1. 饿汉式【静态常量】
  2. 饿汉式【静态代码块】
  3. 懒汉式【线程不安全】
  4. 懒汉式【线程安全,同步方法】
  5. 懒汉式【线程安全,同步代码块】
  6. 双重检查
  7. 静态内部类
  8. 枚举

    3、单例模式注意事项和细节说明

  9. 单例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建和销毁的对象,使用单例模式可以提高系统性能

**

  1. 当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new


  1. 单例模式使用的场景:
    • 需要频繁的进行创建和销毁的对象
    • 创建对象时耗时过多或者耗费资源过多(重量级对象)
    • 不常用的对象,工具类对象
    • 频繁访问数据库或文件的对象(例如:数据源,session工厂等)


  1. 单例模式在JDK中的Runtime类中使用到了(饿汉式)

4、八种单例设计模式

4.1 懒汉式:静态常量

4.1.1 步骤如下:

  1. 构造器私有化 (不能通过new得到对象)

**

  1. 类的内部创建对象 【定义一个常量对象】

**

  1. 向外面暴露一个静态的公共方法 getInstance()

**

4.1.2 代码实现

  1. //单例模式 静态常量 饿汉式
  2. public class Type1 {
  3. public static void main(String[] args) {
  4. Singleton instance = Singleton.getInstance();
  5. Singleton instance2 = Singleton.getInstance();
  6. //发现这两个实例的内存地址是相同的。
  7. System.out.println(instance == instance2);//true
  8. }
  9. }
  10. class Singleton{
  11. //1.构造器私有化
  12. private Singleton(){}
  13. //2.本类内部创建对象实例 【在类的加载的时候就创建了对象实例】[静态常量]
  14. private final static Singleton INSTANCE = new Singleton();
  15. //3.提供一个静态的getInstance()方法
  16. public static Singleton getInstance(){
  17. return INSTANCE ;
  18. }
  19. }

4.1.3 优缺点:

  1. 优点:这种写法比较简单,就是在类装载的时候就完成了实例化,避免了线程同步问题。


  1. 缺点:在类装载的时候就完成了实例化,没有达到懒加载的效果,如果从始至终从未使用过这个对象,则会造成内存的浪费。


  1. 这种方式基于类加载机制避免了很多线程同步问题,不过,intstance在类装载时就实例化,在单例模式中大多数都是调用getInstance方法,但是导致类装载的原因有很多种,因此不能确定有其他的方式(或者其他的静态方法)导致类装载,这时初始化instance就没有达到懒加载的效果


  1. 结论:这种单例模式可用,但是有可能会造成内存泄漏

4.2 饿汉式:静态代码块

4.2.1 步骤如下:

  • 构造器私有化 (不能通过new得到对象)

**

  • 在静态代码块中创建单例对象

**

  • 向外面暴露一个静态的公共方法 getInstance()

**

4.2.2 代码实现

  1. class Singleton2{
  2. //成员变量
  3. private static Singleton2 instance;
  4. //1.构造器私有化
  5. private Singleton2(){}
  6. //2.在静态代码块中创建对象,并复制给成员变量
  7. static {
  8. instance = new Singleton2();
  9. }
  10. //3.提供一个静态的getInstance()方法
  11. public static Singleton2 getInstance(){
  12. return instance;
  13. }
  14. }

4.2.3 饿汉式的静态代码块实现优缺点:

  • 这种方式和上面的类似,只不过将类的实例化的过程放在了静态代码块中,也是在类加载的时候,就执行静态代码块中的代码,初始化类的实例,优缺点和上面是一样得

  • 结论:这种单例模式可用,但是有可能会造成内存泄漏


4.3 懒汉式:线程不安全

4.3.1 步骤如下:

  1. 创建一个私有静态属性
  1. 构造器私有化
  1. 创建一个getInstance()静态方法,在使用到该对象的时候再创建该对象

4.3.2 代码实现:

  1. class Singleton3{
  2. //成员变量
  3. private static Singleton3 instance;
  4. //1.构造器私有化
  5. private Singleton3(){}
  6. //2.提供一个静态的getInstance()方法
  7. //当使用该方法时,才去创建实例,既懒汉式
  8. public static Singleton3 getInstance(){
  9. if (instance == null){
  10. instance = new Singleton3();
  11. }
  12. return instance;
  13. }
  14. }

4.3.3 优缺点:

  1. 起到了懒加载的效果(在使用时才创建),但是只能在单线程下使用


  1. 如果在多线程下,一个线程进入了if中判断,还未来得及往下执行,另一个线程也通过了这个if判断语句,这时便会产生多个实例,所以在多线程环境下不可以使用这种方式


  1. 结论:在实际开发中,不要使用这种方式

4.4 懒汉式:线程安全,同步方法

  1. 步骤如下:
    • 和上面一样,就是在静态方法中加入了 synchronized关键字