设计模式
注意:括号中为八股在每次面试中出现的概率
单例设计模式(357/1759=20.3%)
单例设计模式是一种创建型设计模式,核心思想是保证一个类在整个应用中只有一个实例,并提供一个全局的访问入口。它常用于管理共享资源,比如配置、缓存或数据库连接等场景。接下来,我将详细介绍单例模式的实现过程,以常用的懒汉式加双重检查锁定为例说明其设计原理:
首先,为了避免外部直接创建对象,我们将该类的构造方法设为私有。这一步确保了实例只能在类内部被创建,从而杜绝了通过 new 关键字产生多个实例的可能性。
其次,在类内部定义一个私有的静态变量,该变量用于存储单例实例。初始状态下,它的值为 null,这意味着实例尚未被创建。
然后,我们提供一个公共的静态方法来获取该实例。该方法首先判断静态变量是否为 null,如果不为 null,则说明实例已存在,直接返回即可;如果为 null,则进入同步代码块。在同步块内,再次检查实例是否为 null,若仍为 null,则创建该实例。通过双重检查锁定的方式,我们既保证了多线程环境下的线程安全,又避免了每次访问实例时都进行同步操作带来的性能开销。
最后,当实例创建完成后,后续调用获取实例的方法时,都会直接返回该唯一的实例。这样不仅保证了全局唯一性,也提高了系统性能,因为同步操作只在第一次创建实例时执行。
如何记忆:
1.联想记忆法
场景:
单身公寓
解释 :
单例模式就像一栋单身公寓,整栋楼只能住一个人(唯一实例)。为了保证这一点:
公寓的门钥匙(构造方法)被房东(类)保管,不允许租客(外部代码)私自复制钥匙。
房东在房间里放了一张床(静态变量),用来标记是否已经有人入住。
如果有人敲门(调用获取实例的方法),房东会先看看房间里是否有人(第一次检查),如果没有,他会锁上门再确认一次(双重检查锁定),然后安排人入住。
拓展:
1.单例模式的经典实现方式对比
(1)饿汉式(静态常量)
public class Singleton { private static final Singleton INSTANCE = new Singleton(); private Singleton() {} public static Singleton getInstance() { return INSTANCE; } }
特点:类加载时立即初始化,线程安全。
优点:实现简单,无并发问题。
缺点:即使未使用也会占用资源,可能造成浪费。
(2)懒汉式(线程安全)
public class Singleton { private static Singleton instance; private Singleton() {} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
特点:首次调用时初始化,通过synchronized保证线程安全。
缺点:每次调用getInstance()都会同步,性能较低。
(3)双重检查锁(Double-Check Locking)
public class Singleton { private static volatile Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
关键点:通过两次判空减少同步开销,volatile防止指令重排。
适用场景:高并发环境下的延迟初始化。
(4)静态内部类
public class Singleton { private Singleton() {} private static class Holder { static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return Holder.INSTANCE; } }
优势:利用类加载机制保证线程安全,同时实现延迟初始化。
推荐场景:兼顾性能与安全性的通用方案。
(5)枚举单例
public enum Singleton { INSTANCE; // 添加业务方法 }
特点:天然线程安全,支持序列化,防止反射攻击。
最佳实践:Effective Java推荐的实现方式。
2.Spring 单例 Bean 存在线程安全问题吗?
在多线程环境下,单例 Bean 是否会出现线程安全问题,主要取决于该 Bean 是否维护了可变的共享状态。换句话说,如果一个单例 Bean 中包含可变成员变量,并且多个线程会同时对这些变量进行读写操作,那么就有可能发生线程安全问题。反之,如果该 Bean 不存在可变共享数据,或者所有操作都在内部做好了线程安全的保护,就不会出现线程安全隐患。
常见的处理思路包括:
保持 Bean 的无状态化:尽量只使用不可变成员变量,或者在需要存储状态时,将这些状态放到方法内部,避免多线程同时访问同一份数据。
使用 ThreadLocal:为每个线程提供独立的变量副本,从而隔离线程之间的共享数据,避免竞争。
加锁或其他同步手段:如果必须在 Bean 中操作可变状态,可以使用 synchronized、ReentrantLock 等机制来保证并发操作的安全性。
因此,如果你的单例 Bean 仅用于提供一些纯计算或无状态的业务逻辑(例如常见的 Dao、Service 等),通常无需额外处理多线程问题;但如果其中包含可变共享资源,就需要通过合适的线程安全措施来保证应用的正确性和稳定性。
工厂设计模式(411/1759=23.4%)
工厂设计模式是一种创建型设计模式,它主要用于封装对象的创建过程,从而使客户端不需要直接实例化具体的类,而是通过工厂来获取对象。这种模式提高了代码的灵活性和扩展性。接下来我会详细讲述工厂设计模式的实现过程。
当我们需要创建一个产品对象时,
首先,我们会定义一个抽象的产品接口或者抽象类,明确规定产品的公共行为和属性。这样,无论后续添加多少具体产品,客户端都可以通过同一接口来操作它们。
其次,我们实现具体的产品类,这些类分别实现了抽象产品接口,包含各自独特的业务逻辑和功能。
接着,我们定义一个工厂接口或者抽象工厂类,声明一个创建产品对象的方法。该方法的职责是隐藏具体产品对象的实例化过程,客户端只需要调用这个方法即可获得产品实例。
然后,我们实现具体的工厂类,它们根据传入的参数或内部逻辑,决定创建哪一种具体的产品对象。这样,具体产品的创建细节完全被封装在工厂内部,客户端无需关心对象的创建过程。
最后,当客户端需要一个产品时,它只需调用工厂提供的创建方法,获得对应的产品对象,并直接使用。这种方式不仅降低了客户端与具体产品实现之间的耦合,也方便了系统的扩展和维护。
如何记忆:
1.联想记忆法
场景:
餐厅点餐
解释 :
抽象产品 :菜单上的菜品名称和描述(比如“牛排”)。
具体产品 :厨房实际制作的牛排、意大利面等具体菜品。
抽象工厂 :服务员的职责是接受订单并通知厨房制作菜品。
具体工厂 :厨师根据订单制作具体的菜品。
客户端 :顾客只需要点餐,不需要知道牛排是怎么做出来的。
拓展:
1.分类与实现方式
(1)简单工厂模式(Simple Factory)
简单工厂模式并不是一种正式的设计模式,但它是最基础的形式。它通过一个工厂类根据传入的参数决定创建哪种具体产品。
public class SimpleFactory { public static Product createProduct(String type) { if ("A".equals(type)) { return new ConcreteProductA(); } else if ("B".equals(type)) { return new ConcreteProductB(); } throw new IllegalArgumentException("Unknown type"); } } // 抽象产品 public interface Product { void use(); } // 具体产品A public class ConcreteProductA implements Product { @Override public void use() { System.out.println("Using Product A"); } } // 具体产品B public class ConcreteProductB implements Product { @Override public void use() { System.out.println("Using Product B"); } }
特点:集中管理对象创建逻辑,易于理解和实现。
缺点:违反开闭原则,新增产品时需修改工厂类。
(2)工厂方法模式(Factory Method)
工厂方法模式通过定
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
神哥引路,稳稳起步!!早鸟特惠,仅剩177名额!晚了就涨到29.9了! 核心亮点: 1.数据驱动,精准高频:基于1759篇面经、24139道八股题,精准提炼真实高频八股。 2.科学记忆,高效掌握:融合科学记忆法和面试表达技巧,记得住,说得出。 3.提升思维,掌握财商:不仅可学习八股,更可教你变现,3个月赚不回购买价,全额退。 适宜人群: 在校生、社招求职者及自学者。