设计模式之单例模式

文章目录


一、什么是单例模式

正常类:你 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 保证绝对线程安全
  • 反射拿不到私有构造,无法破坏单例
  • 序列化、反序列化也不会产生新对象
    ✅ 面试问:最好的单例写法?答:枚举
相关推荐
HEADKON4 小时前
司拉德帕失代偿期肝硬化及胆道梗阻患者禁止使用,肝酶升高需暂停药物
单例模式
狂人开飞机4 小时前
01. 工厂模式(Factory Pattern)
设计模式·c#
阿狸猿5 小时前
论软件设计模式及其应用
设计模式
workflower6 小时前
具身智能-三层结构
人工智能·设计模式·动态规划·软件工程·scrum
我爱cope6 小时前
【Agent智能体10 | 反思设计模式-AI数据分析的可视化实战】
人工智能·设计模式·数据分析
老码观察6 小时前
设计模式实战解读(七):适配器模式——让不兼容的接口无缝协作
java·设计模式·适配器模式
人月神话-Lee1 天前
【图像处理】框架设计——协议、值类型与工程化思维
图像处理·人工智能·ios·设计模式·架构·ai编程·swift
AI大法师1 天前
Xbox回归经典绿
大数据·设计模式·xbox
老码观察1 天前
设计模式实战解读(六):装饰器模式——功能增强,不动原代码
java·设计模式·装饰器模式