设计模式之单例模式

文章目录


一、什么是单例模式

正常类:你 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 保证绝对线程安全
  • 反射拿不到私有构造,无法破坏单例
  • 序列化、反序列化也不会产生新对象
    ✅ 面试问:最好的单例写法?答:枚举
相关推荐
怕浪猫20 小时前
领域特定语言(Domain-Specific Language, DSL)
设计模式·程序员·架构
Larcher3 天前
AI Loop:让AI像人一样自主完成任务的核心机制
javascript·人工智能·设计模式
咖啡八杯4 天前
GoF设计模式——享元模式
java·spring·设计模式·享元模式
:mnong4 天前
学习创建结构行为设计模式
设计模式
w_t_y_y4 天前
Agent设计模式(四)多模态融合模式(Multi-Modal Fusion)
设计模式
zhouhui0014 天前
订单状态的 if-else 地狱上线就崩——状态模式的工业级落地
设计模式
geovindu4 天前
go: Reactor Pattern
开发语言·后端·设计模式·golang·反应器模式
一只旭宝5 天前
【C++入门精讲22】常见设计模式
c++·设计模式
许彰午5 天前
38_Java设计模式之装饰器模式
java·设计模式·装饰器模式