设计模式之单例模式

文章目录


一、什么是单例模式

正常类:你 new 一次,我 new 一次,每人一个新对象。都会在堆中创建一份空间。

java 复制代码
User u1 = new User();
User u2 = new User();
//== 比较的是:对象的内存地址
// 判断是不是同一个对象
if(u1 == u2){
     System.out.println("u1 和 u2 是同一个对象");
 }else{
     System.out.println("u1 和 u2 是两个完全不同的对象");
 }
// 输出:u1 和 u2 是两个完全不同的对象

单例模式:不管程序里写多少次获取对象,永远只能有唯一一个对象,全程序共用这一个。

单例模式定义:

一个类只能有一个实例对象,并且提供一个全局访问入口,整个应用全程共用这一个对象。

核心特点:

  • 构造方法私有,外部不能 new
  • 类内部自己创建唯一实例
  • 对外提供静态方法获取这个唯一实例

实现单例模式核心三步

  1. 私有化构造器:private 类名(){} 禁止外部 new
  2. 私有静态实例:private static 类名 instance;
  3. 公共静态获取方法:public static 类名 getInstance(){ return 类}

二、饿汉式单例模式

2.1 饿汉式(静态常量)

java 复制代码
public class Singleton {
    //1.类加载时直接创建实例
    private static final Singleton instance = new Singleton();

    //2.私有构造,防止外部new
    private Singleton() {

    }

    //3.对外获取实例
    public static Singleton getInstance() {
        return instance; //返回唯一的实例对象
    }
}

通俗理解

饿汉:很饿,一上来就先把对象造好等着

  1. 程序启动、类一加载,立马创建唯一对象
  2. 以后别人来拿,直接返回已经造好的

优点:写法简单、多线程绝对安全,不会造出多个对象、避免多线程问题

缺点:类加载就初始化,不用也会占用内存,如果这个对象很大、又一辈子不用,浪费资源

适用:单例类占用内存小、一定会用到

2.2 饿汉式(静态代码块)

java 复制代码
public class Singleton {
    private static Singleton instance;

    static {
        instance = new Singleton();
    }

    private Singleton(){}

    public static Singleton getInstance(){
        return instance;
    }
}

三、懒汉式

3.1 懒汉式(线程不安全)

java 复制代码
public class Singleton {
    private static Singleton instance;

    private Singleton(){}

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

通俗理解

懒汉:很懒,你不来找我,我就不创建对象

  1. 程序启动不创建
  2. 第一次调用 getInstance() 才创建
  • 优点:懒加载,用的时候才创建,省内存
  • 缺点:多线程下不安全,可能创建多个对象。两个线程同时走到 if(instance == null),都判断为空,各自 new 了一个对象,单例被破坏。

只能用在单线程环境,多线程直接废弃。

3.2 懒汉式(同步方法)

java 复制代码
public class Singleton {
    private static Singleton instance;

    private Singleton(){}

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

优点:线程安全、懒加载

缺点:以后每次拿对象都要排队等锁,并发量大的时候性能很差,没必要。


四、静态内部类写法

java 复制代码
public class Singleton {
    // 私有构造
    private Singleton(){}

    // 静态内部类
    private static class Inner{
        private static final Singleton INSTANCE = new Singleton();
    }

    // 对外获取
    public static Singleton getInstance(){
        return Inner.INSTANCE;
    }
}

原理:

  • 外部类加载不会初始化内部类
  • 调用 getInstance() 才加载内部类,才创建对象,实现懒加载
  • JVM 加载静态内部类天然线程安全,不用自己加锁

五、枚举单例

java 复制代码
public enum SingletonEnum {
    // 唯一实例
    INSTANCE;

    // 可以写业务方法
    public void test(){
        System.out.println("单例方法");
    }
}

使用:

java 复制代码
SingletonEnum.INSTANCE.test();
  • JVM 保证绝对线程安全
  • 反射拿不到私有构造,无法破坏单例
  • 序列化、反序列化也不会产生新对象
    ✅ 面试问:最好的单例写法?答:枚举
相关推荐
雪度娃娃1 天前
设计模式-UML
设计模式
kyriewen111 天前
代码写成一锅粥?3个设计模式让你的项目“起死回生”
开发语言·前端·javascript·设计模式·ecmascript
geovindu1 天前
go: Mediator Pattern
设计模式·golang·中介者模式
kyriewen2 天前
代码写成一锅粥?3个设计模式让你的项目“起死回生”
前端·javascript·设计模式
Pkmer2 天前
古法编程: 适配器模式
java·设计模式
rKWP8gKv72 天前
单例模式在Java中的7种实现:从懒汉式到静态内部类
java·开发语言·单例模式
灰子学技术3 天前
Envoy 使用的设计模式技术文档
设计模式
Carl_奕然3 天前
【智能体】Agent的四种设计模式之:ReAct
人工智能·设计模式·语言模型