Java 设计模式面试问答

2025年3月17日 | 阅读16分钟
Java Design Pattern Interview Questions

设计模式通常是软件开发行业中使用的标准化实践集合。它们代表了社区为日常软件开发任务中遇到的常见问题提供的解决方案。

这些模式提供可重用的蓝图,可加快常见功能的实现,从而促进不同领域的一致性和效率。这些模式结合了经过验证的方法。通过系统地实现,设计模式促进了最佳实践,并有助于解决重复出现的问题,使开发人员能够自信地处理复杂性,并提高软件系统的可维护性和可伸缩性。

让我们讨论最常问的 30 个设计模式面试问题和答案。这些问题将帮助您应对编码面试和竞争性考试。

1) 您对设计模式有什么了解?

设计模式一词来源于建筑领域。这个概念归功于克里斯托弗·亚历山大(Christopher Alexander)。它允许开发人员在设计形状的过程中创建应用程序。两位著名学者肯特·贝克(Kent Beck)沃德·坎宁安(Ward Cunningham)发现设计模式可以在计算机科学中实现。

它是面向对象编程中的一个基本元素。它是一个由少量类组成的软件基础设施。它用于解决技术问题。

设计模式有其起源,因此开发人员注意到了反复出现且类似的设计问题。因此,有必要将设计问题概念化,以便每次出现问题时都能重复使用相同的答案。

为了概念化,通常需要直接使用代码。在设计模式概念中,开发人员将概念化转化为一个抽象的想法(如何克服问题)。然后每个开发人员使用他们熟悉的语言实现问题解决方案。

因此,设计模式被认为是基于软件设计中已获得的经验的通用设计过程。设计模式在计算机系统及其架构中发挥着重要作用。


2) 为什么要使用设计模式?

  • 它加快了开发过程。
  • 它提供了经过验证的开发范例。
  • 它节省了时间。
  • 它以有组织和快速的方式解决每个问题。
  • 当从分析模型转换为开发模型时,它非常有用。
  • 它对于提高代码可读性非常有帮助。
  • 它可以在多种情况下具体使用。
  • 它可以在编程的所有阶段使用。

3) Java 设计模式的类别?

根据问题分析,我们可以将设计模式分为以下几类。

创建型模式

  • 工厂方法/模板
  • 抽象工厂
  • Builder
  • 原型
  • 单例

结构型模式

  • 适配器
  • 桥梁
  • Filter
  • 复合
  • 装饰器
  • 外观
  • 享元
  • Proxy

行为型模式

  • 解释器
  • 模板方法/模式
  • 责任链模式
  • 命令模式
  • 迭代器模式
  • 策略模式
  • 访问者模式
  • J2EE 模式

J2EE 模式

  • MVC 模式
  • 数据访问对象模式
  • 前端控制器模式
  • 拦截过滤器模式
  • 传输对象模式

4) 解释 Java 设计模式的优点?

  1. 跨项目重用性:设计模式封装了最佳实践和常见问题的成熟解决方案。通过实现这些模式,开发人员可以利用预定义的结构和方法,节省在多个项目中设计和实现类似功能的时间和精力。这不仅加快了开发速度,而且促进了不同代码库之间的一致性和标准化。
  2. 定义系统架构:设计模式是定义软件系统架构的构建块。通过整合这些模式,开发人员可以为他们的应用程序建立清晰且有组织的结构,从而促进可伸缩性、可维护性和可扩展性。诸如工厂方法、抽象工厂和建造者等模式有助于定义对象的创建和组成,而诸如 MVC 和前端控制器等模式有助于描绘整体系统架构。
  3. 捕获软件工程经验:设计模式封装了专业软件开发人员的集体知识和经验。它们体现了从现实世界挑战和随着时间推移获得的经验教训中获得的解决方案。通过利用这些模式,开发人员可以受益于他人的见解和专业知识,避免常见陷阱并实施经过验证的复杂问题解决方案。
  4. 应用程序设计的透明性:设计模式提供了设计软件应用程序的透明且结构化的方法。通过遵循既定模式,开发人员可以提高其代码的清晰度和可读性,使其更易于理解、维护和重构。诸如装饰器和代理等模式通过允许在不改变现有代码库的情况下添加功能来促进模块化和透明的设计。
  5. 经过测试和验证的可靠性:设计模式经受住了时间的考验,并通过软件开发社区的广泛使用和审查得到了验证。它们为重复出现的问题提供了可靠而强大的解决方案,并得到了经验丰富的开发人员的专业知识和经验的支持。通过整合这些模式,开发人员可以降低风险并确保其软件系统的稳定性和效率。

5) 什么是四人帮(GoF)?

1994 年,四位作者 Erich Gamma、Ralph Johnson、Richard Hel 和 John Vlissides 出版了一本名为《设计模式:可重用面向对象软件的元素》的书。这本书介绍了软件开发中的设计模式概念。这四位作者被称为四人帮(GoF)。

这本书列出了 23 种设计模式,分为三类:创建型、结构型行为型模式。还有一个单独的并发模式类别。这些模式用于解决软件设计和开发过程中出现的典型问题,为开发人员提供解决方案。


6) 什么是创建型模式?

创建型设计模式与对象创建方式有关。创建型设计模式在类实例化时做出决策时使用。

由于 Java 中使用 new 关键字创建对象。在这里,我们使用 new 关键字创建实例。在某些情况下,对象的性质必须根据程序的性质进行更改。在这种情况下,我们应该使用创建型设计模式来提供更通用和灵活的方法。

创建型设计模式提供了创建对象的替代方法,允许开发人员根据特定需求调整实例化过程。例如:

  1. 工厂方法模式:您可以将对象创建委托给工厂方法,而不是直接使用 new 关键字创建对象。该方法可以根据某些条件或参数确定要创建的对象类型,从而提供更灵活的对象创建方法。
  2. 抽象工厂模式:此模式提供了一个接口,用于创建相关或依赖对象的家族,而无需指定它们的具体类。它允许您创建具有不同实现的对象,同时确保同一家族中的兼容性。
  3. 建造者模式:如果对象创建涉及复杂的构建过程或需要设置多个参数,则可以使用建造者模式将对象的构建与其表示分离。这允许使用一致的构建过程创建具有不同配置的对象。
  4. 原型模式:原型模式不是从头开始创建新对象,而是涉及克隆现有对象(原型)。当创建具有相似初始状态或配置的对象时,此方法非常有用,减少了重复初始化代码的需要。
  5. 单例模式:在整个应用程序中只需要一个类实例的情况下,单例模式可确保创建一个单一实例并提供对其的全局访问点。此模式通常用于管理共享资源或维护全局状态。

7) 什么是工厂模式?

  • 它是 Java 中广泛使用的设计模式。
  • 这些设计模式属于创建型模式,因为此模式提供了创建对象的最佳方式之一。
  • 在工厂模式中,我们不向客户端公开创建逻辑,而是使用标准接口引用创建的对象。
  • 工厂模式允许子类选择要创建的对象类型。
  • 工厂模式也称为虚拟构造函数

8) 什么是抽象工厂模式?

抽象工厂模式规定定义一个抽象类或接口,用于创建相关对象的家族,但无需指定其具体的子类。这意味着抽象工厂允许一个类返回一个类工厂。这就是为什么抽象工厂模式比工厂模式高一个级别。

  • 抽象工厂模式围绕创建其他类的超类工作。
  • 抽象工厂模式属于创建型模式,因为此模式提供了创建对象的最佳方式之一。
  • 在抽象工厂模式中,一个接口负责创建相关对象的工厂,而无需显式识别它们的类。
  • 每个生成的工厂都可以根据工厂模式提供对象。

抽象工厂模式的特点

  • 创建抽象:抽象工厂模式抽象了对象创建过程,允许客户端创建相关对象的家族,而无需关注它们的具体实现。
  • 相关对象家族:每个抽象工厂定义了一个相关对象的家族,例如产品线中不同类型的产品或图形用户界面中各种 UI 组件。
  • 具体类的封装:抽象工厂的具体子类封装了对象的特定实现,提供了选择不同实现的灵活性,而不会影响客户端代码。
  • 一致性和兼容性:通过使用抽象工厂模式,开发人员可以确保工厂创建的对象彼此兼容和一致,从而促进系统内的互操作性。

9) 解释 Java 中的结构型模式?

结构型模式用于提供有关类组合和对象结构的解决方案和高效标准。它们依赖于继承和接口的概念,以允许多个对象或类协同工作并形成一个单一的整体。

结构型设计模式负责类和对象如何组合以形成更大的结构。


10) 解释单例模式?

Java 中的单例模式允许应用程序中只有一个实例。单例模式的一个很好的例子是 Java.lang.Runtime。

单例模式规定定义一个只有一个实例并提供对其全局访问点的类。

换句话说,创建一个单一实例是该类的责任,所有其他类都可以使用该单一对象。

单例类通常提供一个静态方法来访问在第一次调用期间延迟或急切创建的单一实例。它通常采用私有构造函数来防止外部实例化和静态成员变量来保存唯一的实例。单例模式在日志记录、数据库连接、缓存、线程池和配置设置等场景中非常有用,在这些场景中,拥有多个实例可能导致不一致的行为或资源浪费。


11) 创建单例模式有多少种方式,请描述。

创建单例模式有以下两种方式:

  1. 饿汉式:它负责在加载时创建实例。
  2. 懒汉式:它负责在需要时创建实例。

除了这两种方法之外,每种方法中还有变体和优化,例如:

  • 双重检查锁定:一种用于延迟初始化的优化,通过仅在单例实例尚未初始化时锁定代码的关键部分来减少同步开销。
  • 初始化按需持有者习语(静态嵌套类):利用 Java 语言保证在引用之前不会加载类,并结合静态字段的初始化来实现延迟实例化而无需显式同步。
  • 枚举单例:利用 Java 枚举创建单例实例,自动确保线程安全并处理序列化/反序列化问题。
  • Bill Pugh 单例:利用静态内部辅助类延迟创建单例实例,同时确保线程安全而无需显式同步。

12) 什么是适配器模式?

适配器模式根据需求将一个类的接口转换为另一个接口。

换句话说,它允许您在使用具有不同接口的类服务时,根据需要转换接口。

它也被称为包装器(Wrapper)。


13) 说明适配器模式的用途?

它用于以下情况:

  1. 与遗留代码集成:当我们需要将新代码与具有不同接口的现有遗留代码集成时,适配器模式可以通过调整新代码的接口以匹配遗留代码的接口来弥合差距。
  2. 第三方库:当我们要使用一个不符合应用程序预期接口的第三方库时,我们可以创建一个适配器,使该库与您的代码库兼容,而无需修改库本身。
  3. 接口标准化:在多个类或系统具有不同接口但需要标准化才能协同工作的场景中,可以创建适配器来统一接口并促进它们之间的无缝通信。
  4. 可重用性:适配器可用于通过调整其接口以与具有不同接口要求的各种客户端类或系统一起工作来使类可重用。它促进了应用程序中的代码重用和模块化。
  5. 测试:适配器在测试环境中非常有用,在测试环境中需要创建模拟对象或存根以模拟真实对象的行为。适配器可以调整这些模拟对象的接口以匹配被测试代码预期的接口。

14) 讨论描述设计模式的策略?

描述设计模式时需要注意以下几点。

  • 模式名称和分类。
  • 问题和解决方案。
  • 结果:还应解决变体和依赖于语言的替代方案。
  • 用途:识别真实系统中的用途及其效率。

15) Java 中的装饰器模式是什么?请举例说明?

装饰器模式是 Java 中流行的设计模式之一。它因在 java.io(包)中的大量使用而闻名。装饰器模式使用组合而不是继承来在运行时扩展对象的功能。

BufferedReaderBufferedWriter 是 Java 中装饰器模式的一些很好的例子。


16) Java 中策略模式和状态设计模式的区别?

这个问题是一个常见的 Java 设计模式面试问题,因为策略模式和状态模式具有相同的结构。两种模式的 UML 类图看起来完全相同,但它们的意图不同。

状态设计模式用于管理和定义对象的状��,而策略模式用于描述一组可互换的算法。


17) Java 中组合设计模式的优点是什么?

组合设计模式允许客户端集体操作可能或不表示对象层次结构的对象。

组合设计模式的优点如下。

  • 它描述了包含原始对象和复杂对象的类层次结构。
  • 它使添加新类型的组件变得容易。
  • 它通过可管理的类或接口促进结构的灵活性。

18) 讨论组合模式的三个用途?

它用于以下情况:

  1. 分层结构:组合模式非常适合建模分层结构,其中单个对象和对象组合共享一个共同的接口。示例包括组织结构图、文件系统、GUI 组件和嵌套菜单。
  2. 递归行为:当我们需要在树状结构上递归执行操作时,组合模式提供了一种统一的方式来遍历和操作层次结构中的元素。它简化了代码,并促进了处理单个对象和对象组合时的一致性。
  3. 统一访问:组合模式使客户端能够统一地与复杂结构交互,以相同的方式处理单个对象和对象组合。这使得处理复杂结构变得更容易,而无需了解每个元素的内部细节。

17) 说出 JDK 库中使用的设计模式?

JDK 库中使用的某些设计模式如下。

  • 包装器类使用装饰器模式。
  • Calendar 类(运行时)使用单例模式。
  • 包装器类使用工厂模式,如 Integer.valueOf。
  • 事件处理框架使用观察者模式,如 swing、awt。

20) Java 中建造者设计模式的优点是什么?

建造者设计模式的优点如下:

  • 它促进了对象的构造和表示之间的清晰分离。
  • 它提供了对构造过程的改进控制。
  • 构造函数参数减少,并在高度可读的方法调用中提供。
  • 在设计模式中,对象总是以完整状态实例化。
  • 在建造者设计模式中,不可变对象可以在对象构建过程中快速构建。

21) 是否可以在 Java 中编写线程安全的单例?如果可以,请讨论?

在 Java 中编写线程安全的单例有多种方法。

  • 可以通过使用双重检查锁定来编写单例来实现线程安全的单例。
  • 另一种方法是,在类加载期间初始化静态单例实例。
  • 通过使用 Java 枚举创建线程安全的单例,这是最直接的方法。

22) 是否可以克隆单例对象?

是的,可以克隆单例对象。确保在应用程序的整个生命周期中只有一个类实例是单例模式的全部目标。将类的实例化限制为一个实例有助于实现这一点。克隆单例对象将通过生成第二个实例来违背单例模式的意图,这违反了这一原则。

此外,许多单例模式实现会覆盖 Object 类的 clone() 方法以抛出 CloneNotSupportedException,明确禁止克隆单例实例。


23) 什么是代理模式,它有什么作用?

“代理”一词表示代表另一个对象的对象。代理模式为另一个目的提供替代品或占位符,以控制对它的访问。

根据四人帮的说法,代理模式“提供了访问原始对象的控制权”。

我们可以执行许多安全操作,例如隐藏原始对象的信息、按需加载等。

它也称为占位符或替代品。


24) 解释一些不同类型的代理?

在许多情况下,代理模式都很有用。让我们看看一些不同的代理。

保护代理:它根据某些条件控制对真实主题的访问。

虚拟代理:虚拟代理用于实例化开销大的对象。在实现中,代理管理真实主题的生命周期。

它决定何时需要创建实例以及何时重用它。虚拟代理优化了性能。

缓存代理:缓存代理用于缓存对真实主题的开销大的调用。代理可以使用许多缓存策略。

其中一些是读穿式、写穿式、旁路缓存和基于时间的缓存。缓存代理用于提高性能。

远程代理:远程代理用于分布式对象通信。远程代理通过调用本地对象方法在远程对象上执行。

智能代理:智能代理用于实现对对象的日志调用和引用计数。


25) 解释责任链模式?

在责任链模式中,发送者向一系列对象发送请求,链中的任何对象都可以处理该请求。

责任链模式避免了请求发送者与其接收者之间的耦合。例如,ATM 服务在货币交易中使用责任链设计模式。

此外,我们可以解释说,通常,每个接收者都包含另一个接收者的引用。如果一个对象无法处理请求,它就会将相同的请求发送给下一个接收者,依此类推。


26) 解释责任链模式的优点以及何时使用它?

优点

  • 它最大限度地减少了耦合。
  • 它在为对象分配职责时提供了灵活性。
  • 它允许一组类作为一个整体运行。一个类中产生的事件可以通过组合发送给其他处理程序类。

用途

它用于以下情况:

  • 当有多个对象准备好处理请求,并且处理程序未知时。
  • 在必须动态指定可以处理请求的对象集合或组的情况下。

27) 桥接模式与适配器模式有何不同?

适配器模式的目的是使一个或多个类的接口看起来相似。

桥接模式旨在将类的接口与其实现隔离,以便我们可以在不更改客户端代码的情况下更改或替换实现。


28) 依赖注入和服务定位器模式之间有什么区别?

服务定位器用于创建类依赖项。无论是否使用服务定位器,类仍然负责创建其依赖项。

服务定位器还用于隐藏依赖项。通过查看对象,我们无法判断它是否连接到数据库,因为它从定位器获取连接。

使用依赖注入,包含其依赖项的类既不知道也不关心它们来自哪里。

一个显著的区别是依赖注入更容易进行单元测试,因为我们可以在其中传递其依赖对象的模拟实现。我们可以组合这两个对象并应用服务定位器。


29) 什么是 MVC 模式?

该模式是 J2EE 设计模式类别中使用最广泛的模式之一。它与模型-视图-控制器概念非常相似。缩写 MVC 取自模型-视图-控制器概念。

模型是对象,用作应用程序中所有对象��蓝图。

视图包含模型中数据和信息的表示方面。

控制器控制模型和视图,因为它们充当两个对象之间的连接。控制器扮演视图和模型之间接口的角色,并拦截所有传入请求。


30) 解释拦截过滤器设计模式并提及其优点?

拦截过滤器设计模式用于在请求处理之前和之后拦截和操纵请求和响应。过滤器执行请求的认证/授权/日志记录或跟踪,然后将请求转发给相应的处理程序。让我们看看拦截设计模式的一些基本实体。

过滤器:它在请求处理程序执行请求之前或之后执行特定任务。

过滤器链:它包含多个过滤器,并有助于按定义的顺序在目标上执行它们。

目标:目标对象是请求处理程序

过滤器管理器:它管理过滤器和过滤器链。

客户端:客户端对象是向目标对象发送请求的对象。

拦截过滤器设计模式的优点

  • 过滤器模式通过松散耦合的处理程序提供集中控制。
  • 它扩展了可重用性。
  • 新过滤器可以随时添加,而不会影响客户端代码。
  • 过滤器可以在程序执行期间动态选择。

31) 解释数据访问对象(DAO)模式?

数据访问对象模式用于将低级数据访问 API 或操作与高级业务服务隔离。DAO 模式中的组件如下。

数据访问对象接口:DAO 接口描述了对模型对象执行的标准操作。

数据访问对象具体类:此实现 DAO 接口的类。此负责从数据源(可以是 Xml/数据库或任何其他存储机制)获取数据。

模型对象或值对象:此对象是一个普通的 Java 对象,包含用于存储使用 DAO 类检索的数据的 get/set 方法。


32) VO 和 JDO 有什么区别?

标准VO(值对象)JDO(Java 数据对象)
目的代表一种抽象设计模式。一种用于在数据库中存储 Java 对象的持久化技术。
用途与实体 Bean、JDBC 和 JDO 结合使用。用于创建 POJO(普通 Java 对象)并将其持久化到数据库。
持久化通常不直接负责持久化。直接负责 Java 对象的持久化。
依赖性可与各种持久化机制一起使用。通常用作实体 Bean 的持久化替代方案。
灵活性在与不同持久化策略一起使用方面提供灵活性。提供了一种标准化方法来持久化 Java 对象。
可扩展性适用于各种应用程序架构。适用于可伸缩和分布式应用程序。
易用性实现相对简单。可能需要学习曲线才能理解和配置。
交易可能不提供内置事务管理。提供内置事务管理功能。