单例模式的7种写法及其应用场景你都熟悉了吗,快来看看吧

单例模式的7种写法

  • 定义
    • 单例模式的写法有以下7种
      • 1. 饿汉式(静态常量)
      • 2. 懒汉式(线程不安全)
      • 3. 懒汉式(线程安全,同步方法)
      • 4. 懒汉式(线程安全,同步代码块)
      • 5. 双重检查
      • 6. 静态内部类
      • 7. 枚举
      • 单例应用场景
      • 单例模式注意事项和细节说明

  设计模式(Design pattern),提供了在软件开发过程中面临的一些问题的解决方案,主要分创建型模式、结构型模式和行为型模式。其中的单例模式,属于创建型模式。

  而单例模式是在学习中最常见的一种,而就这一种模式在实现上就有好多种写法,而且每种写法之间都有一些联系和它们的使用场景。那废话不多说,快上车,我们一起看看吧。

定义

  单例模式:单例模式就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其实例的方法。

单例模式的写法有以下7种

1. 饿汉式(静态常量)

步骤

  1. 构造器私有化(防止new)
  2. 类的内部类创建对象
  3. 向外暴露一个静态的公共方法
  4. 代码实现

代码实现

// 饿汉式
class Singleton {
    //构造器私有化
    private Singleton() {}
    
    //本类内部创建对象实例
    private final static  Singleton instance = new Singleton();

    //提供一个公有的静态方法,返回实例对象
    public static Singleton getInstance() {
        return instance;
    }
}

优缺点:

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

  • 线程安全
  • 在类加载的同时已经创建好一个静态对象,调用时反应速度快

  缺点:来类装载的时候就完成了实例化,没有达到Lazy Loading的效果。如果从始至终未使用过这个实例,则会造成实例的浪费。

2. 懒汉式(线程不安全)

代码

//懒汉式(线程不安全)
class Singleton {
    private Singleton() {}

    private static Singleton instance;

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

缺点:

  • 起到了Lazy Loading的效果,但是只能在单线程下使用。
  • 多线程下,一个线程进入了if (singleton == null)判断语句块,还未来得及 往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。

3. 懒汉式(线程安全,同步方法)

//懒汉式(线程安全, 同步方法)
class Singleton {
    private Singleton() {}

    private static Singleton instance;

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

优点:解决了线程不安全问题。

缺点:效率太低。

4. 懒汉式(线程安全,同步代码块)

class Singleton {
    private Singleton() {}

    private static Singleton instance;

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                instance = new Singleton();
            }
        }
        return instance;
    }
}

优点:解决方法3效率低的问题。

5. 双重检查

//懒汉式(双重检查)
class Singleton {
    private Singleton() {}

    private static volatile Singleton instance;

    //提供一个公共方法,加入双重检查,解决线程问题,同时解决懒加载问题
    //同时保证了效率
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if(instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

优点:线程安全;延迟加载;效率较高

6. 静态内部类

//懒汉式(静态内部类)
class Singleton {
    private Singleton() {}

    //写一个静态内部类,该类中有一个静态属性Singleton
    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static synchronized Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}

优点:避免了线程不安全,利用静态内部类特点实现延迟加载,效率高。

7. 枚举

public class singleton1 {
    public static void main(String[] args) {
        Singleton singleton = Singleton.INSTANCE;
        Singleton singleton1 = Singleton.INSTANCE;
        
        System.out.println("singleton.hashCode() :" + singleton.hashCode());
        System.out.println("singleton1.hashCode() :" + singleton1.hashCode());

        System.out.println(singleton == singleton1);

        singleton.sayOk();
    }
}

//使用枚举可以实现单例
enum Singleton {
    INSTANCE;
    public void sayOk() {
        System.out.println("OK");
    }
}

结果输出

singleton.hashCode() :1360875712
singleton1.hashCode() :1360875712
true
OK

结果显示它们是同一个对象。

优点:不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。

单例应用场景

  1. Windows的Task Manager(任务管理器)就是很典型的单例模式(这个很熟悉吧),想想看,是不是呢,你能打开两个windows task manager吗? 不信你自己试试看哦~

  2. windows的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。

  3. 网站的计数器,一般也是采用单例模式实现,否则难以同步。

  4. 应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。

  5. Web应用的配置对象的读取,一般也应用单例模式,这个是由于配置文件是共享的资源。

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

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

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

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

在学习过程中,既是总结,也是希望能帮到大家,如有纰漏,请留言。

你可能感兴趣的:(java基础,java,设计模式,单例模式)