《JAVA八股真解》五、设计模式

#JAVA##JAVA面经##JAVA内推#

1. 单例模式的几种写法

单例模式确保一个类只有一个实例,并提供全局访问点。以下是几种常见的实现方式:

懒加载 —— 双重检查锁(DCL)模式

public class Singleton {
    private volatile static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) { // 第一次检查
            synchronized (Singleton.class) {
                if (instance == null) { // 第二次检查
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

说明

  • 使用双重检查锁(Double-Checked Locking)确保线程安全。
  • volatile 关键字防止指令重排序,保证多线程环境下的可见性。
  • 在首次调用时才创建实例,实现懒加载。

优点:线程安全,延迟初始化,性能较好。 缺点:代码相对复杂,需注意 JVM 内存模型的影响。

预加载 —— 饿汉模式

public class Singleton {
    private static final Singleton instance = new Singleton();

    private Singleton() {}

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

说明

  • 类加载时即创建实例,属于“饿汉式”。
  • 不需要同步机制,因此性能高。

优点:简单直接,线程安全。 缺点:提前创建对象,可能造成资源浪费。

静态内部类模式

public class Singleton {
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    private Singleton() {}

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

说明

  • 利用 Java 类加载机制实现懒加载和线程安全。
  • 外部类不会立即加载内部类,直到第一次调用 getInstance() 时才会加载。

优点:线程安全,延迟加载,无需额外同步控制。 缺点:不能通过反射破坏单例性,但理解成本略高。

枚举模式(推荐)

public enum Singleton {
    INSTANCE;

    public void doSomething() {
        System.out.println("done");
    }
}

说明

  • 枚举类型天然支持单例,且不可被继承、反射或序列化破坏。
  • 是实现单例模式的最佳实践。

优点:简洁、安全、自动处理序列化与反序列化问题。 缺点:无法继承其他类,灵活性较低。

总结:在实际项目中,优先使用枚举模式实现单例,除非有特殊需求。

2. Spring 中的设计模式有哪些?

Spring 框架广泛运用了多种设计模式,以下是其核心设计模式:

  • 工厂模式

    • Spring 通过 BeanFactoryApplicationContext 创建 Bean 实例。
    • 所有的 Bean 默认都是单例的,符合工厂模式的思想。
  • 单例模式

    • Spring 容器中的每个 Bean 默认为单例,由容器管理生命周期。
  • 代理模式

    • AOP 功能基于 JDK 动态代理或 CGLIB 字节码生成技术实现。
    • 用于实现方法拦截、事务管理、日志记录等功能。

示例:AOP 通过动态代理为目标对象添加横切逻辑,如事务、日志等。

3. MyBatis 中有哪些设计模式?

MyBatis 是一个优秀的持久层框架,也大量使用了设计模式:

  • 工厂模式

    • SqlSessionFactoryObjectFactoryMapperProxyFactory 等,负责创建对象实例。
  • 单例模式

    • ErrorContextLogFactory 等类采用单例模式,确保全局唯一。
  • 代理模式

    • MyBatis 的核心是动态代理,如 MapperProxyConnectionLogger
    • 使用 JDK 动态代理或 CGLIB 实现接口代理。
    • executor.loader 包利用 CGLIB 或 Javassist 实现延迟加载。

作用:通过代理模式将 SQL 映射到接口方法,简化数据库操作。

#JAVA##java##面经#

本专栏在精不在多,内容分为八股文、大厂真实面经,面试通过后将offer和面试题私发给我,可退还专栏的收益部分费用。欢迎大家共建专栏

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务