设计模式 - 面试题



尊敬的读者们,这些设计模式面试题是专门为了让您熟悉在设计模式面试中可能遇到的问题类型而设计的。根据我的经验,优秀的 interviewers 很少会预先计划好要问哪些特定问题,通常问题会从该主题的一些基本概念开始,然后根据后续的讨论和您的回答继续下去。

设计模式代表了经验丰富的面向对象软件开发人员使用的最佳实践。设计模式是对软件开发人员在软件开发过程中遇到的常见问题的解决方案。这些解决方案是众多软件开发人员在相当长的一段时间内通过反复试验获得的。

1994年,四位作者 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 出版了一本名为《设计模式——可复用面向对象软件的基础》的书,该书开启了软件开发中设计模式的概念。这些作者统称为四人帮 (GOF)。

设计模式可以分为三大类:创建型模式、结构型模式和行为型模式。

  • 创建型模式 - 这些设计模式提供了一种创建对象的方式,同时隐藏了创建逻辑,而不是直接使用 new 运算符实例化对象。这使得程序在决定为给定用例需要创建哪些对象方面更具灵活性。

  • 结构型模式 - 这些设计模式关注类和对象的组合。继承的概念用于组合接口并定义组合对象以获得新功能的方法。

  • 行为型模式 - 这些设计模式专门关注对象之间的通信。

这些设计模式专门关注表示层。这些模式由 Sun Java 中心确定。

工厂模式是 Java 中最常用的设计模式之一。这种设计模式属于创建型模式,因为它提供了一种创建对象的最佳方式。

在工厂模式中,我们创建对象而不向客户端公开创建逻辑,并使用公共接口引用新创建的对象。

抽象工厂模式围绕一个超级工厂工作,该超级工厂创建其他工厂。这个工厂也称为工厂的工厂。这种设计模式属于创建型模式,因为它提供了一种创建对象的最佳方式。

在抽象工厂模式中,一个接口负责创建相关对象的工厂,而无需明确指定它们的类。每个生成的工厂都可以根据工厂模式提供对象。

单例模式是 Java 中最简单的设计模式之一。这种设计模式属于创建型模式,因为它提供了一种创建对象的最佳方式。

这种模式涉及一个单一类,该类负责创建对象,同时确保只创建单个对象。此类提供了一种访问其唯一对象的方式,可以直接访问该对象,而无需实例化该类的对象。

这是一个两步过程。首先,将构造函数设为私有,以便 new 运算符不能用于实例化该类。如果对象不为空,则返回该对象的实例,否则创建该对象并通过方法返回。

以下是静态类和单例类之间的区别。

  • 静态类不能是顶级类,也不能实现接口,而单例类可以。

  • 静态类的所有成员都是静态的,但对于单例类来说,这不是必需的。

  • 静态类在加载时被初始化,因此不能延迟加载,而单例类可以延迟加载。

  • 静态类对象存储在堆栈中,而单例类对象存储在堆内存空间中。

可以。

在 clone() 方法的主体中抛出异常。

以下是 JDK 库中使用的一些设计模式。

  • 装饰器模式由包装类使用。

  • 单例模式由 Runtime、Calendar 类使用。

  • 工厂模式由包装类(如 Integer.valueOf)使用。

  • 观察者模式由事件处理框架(如 swing、awt)使用。

工厂模式封装了实现细节,可以在不影响调用者 API 的情况下更改底层实现。

建造者模式使用简单的对象和循序渐进的方法构建复杂对象。此构建器独立于其他对象。

原型模式是指在考虑性能的同时创建重复对象。此模式涉及实现一个原型接口,该接口指示创建当前对象的克隆。

当直接创建对象成本很高时使用此模式。例如,对象需要在代价高昂的数据库操作后创建。我们可以缓存该对象,在下一个请求时返回其克隆,并在需要时更新数据库,从而减少数据库调用次数。

适配器模式充当两个不兼容接口之间的桥梁。此模式涉及一个单一类,该类负责连接独立或不兼容接口的功能。

一个现实生活中的例子可能是读卡器的情况,它充当内存卡和笔记本电脑之间的适配器。您将内存卡插入读卡器,并将读卡器插入笔记本电脑,以便可以通过笔记本电脑读取内存卡。

当我们需要将抽象与其实现解耦时使用桥接模式,以便两者可以独立变化。这种设计模式属于结构型模式,因为它通过在它们之间提供桥接结构来解耦实现类和抽象类。

此模式涉及一个充当桥梁的接口,该接口使具体类的功能独立于接口实现类。两种类型的类都可以在结构上进行更改,而不会相互影响。

过滤器模式或标准模式是一种设计模式,它使开发人员能够使用不同的标准过滤对象集,并通过逻辑运算以解耦的方式将它们链接起来。这种设计模式属于结构型模式,因为它组合了多个标准以获得单个标准。

组合模式用于我们需要以类似于单个对象的方式处理一组对象的情况。组合模式根据树结构组成对象,以表示部分和整体层次结构。这种设计模式属于结构型模式,因为它创建了对象组的树结构。

此模式创建包含其自身对象组的类。此类提供修改其相同对象组的方法。

装饰器模式允许用户向现有对象添加新功能,而无需更改其结构。这种设计模式属于结构型模式,因为它充当现有类的包装器。

此模式创建一个装饰器类,该类包装原始类并提供附加功能,同时保持类方法签名不变。

外观模式隐藏了系统的复杂性,并向客户端提供了一个接口,客户端可以使用该接口访问系统。这种设计模式属于结构型模式,因为它向现有系统添加了一个接口来隐藏其复杂性。

此模式涉及一个单一类,该类提供客户端所需的简化方法,并将调用委托给现有系统类的该方法。

享元模式主要用于减少创建的对象数量,以减少内存占用并提高性能。这种设计模式属于结构型模式,因为它提供了一种减少对象数量从而改进应用程序对象结构的方法。

享元模式尝试通过存储已经存在的类似对象来重用它们,并在找不到匹配的对象时创建新对象。

在代理模式中,一个类代表另一个类的功能。这种设计模式属于结构型模式。

在代理模式中,我们创建具有原始对象的接口来将其功能接口到外部世界。

顾名思义,责任链模式为请求创建接收者对象的链。此模式根据请求类型解耦请求的发送者和接收者。此模式属于行为模式。

在此模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象无法处理请求,则将其传递给下一个接收者,依此类推。

命令模式是一种数据驱动的设计模式,属于行为模式类别。请求被包装在一个对象中作为命令,并传递给调用者对象。调用者对象查找可以处理此命令的适当对象,并将命令传递给执行该命令的相应对象。

解释器模式提供了一种评估语言语法或表达式的方法。这种模式属于行为型模式。这种模式涉及实现一个表达式接口,该接口指示如何解释特定上下文。

这种模式用于SQL解析、符号处理引擎等。

迭代器模式在Java和.Net编程环境中非常常用。此模式用于以顺序方式访问集合对象的元素,而无需了解其底层表示。迭代器模式属于行为型模式。

以下是这种设计模式的实体。

  • 服务 - 将处理请求的实际服务。此类服务的引用将在JNDI服务器中查找。

  • 上下文/初始上下文 - JNDI上下文包含用于查找目的的服务引用。

  • 服务定位器 - 服务定位器是通过JNDI查找获取服务并缓存服务的单点联系。

  • 缓存 - 用于存储服务引用以重用它们。

  • 客户端 - 客户端是通过ServiceLocator调用服务的对象。

中介者模式用于减少多个对象或类之间的通信复杂性。此模式提供一个中介者类,该类通常处理不同类之间的所有通信,并通过松散耦合支持代码的轻松维护。中介者模式属于行为型模式。

备忘录模式用于将对象的状体恢复到之前的状体。备忘录模式属于行为型模式。

备忘录模式使用三个参与者类。备忘录包含要恢复的对象的状体。发起者创建并将状体存储在备忘录对象中,而管理者对象负责从备忘录中恢复对象状体。

当对象之间存在一对多关系时,例如,如果修改了一个对象,则其依赖对象将自动收到通知,则使用观察者模式。观察者模式属于行为型模式。

观察者模式使用三个参与者类:主题、观察者和客户端。主题是一个具有方法的对象,用于将观察者附加和分离到客户端对象。我们创建了一个抽象类观察者和一个扩展观察者类的具体类主题。

在状体模式中,类的行为根据其状体而变化。这种设计模式属于行为型模式。在状体模式中,我们创建表示各种状体的对象和一个上下文对象,其行为随其状体对象的更改而变化。

在空对象模式中,空对象替换了对NULL对象实例的检查。与其对空值进行if检查,不如使用空对象来反映不执行任何操作的关系。如果数据不可用,此类空对象也可用于提供默认行为。

在空对象模式中,我们创建一个抽象类,指定要执行的各种操作,扩展此类的具体类和一个提供此类不执行任何操作实现的空对象类,并在需要检查空值的地方无缝使用。

在策略模式中,可以在运行时更改类的行为或其算法。这种设计模式属于行为型模式。

在策略模式中,我们创建表示各种策略的对象和一个上下文对象,其行为根据其策略对象而变化。策略对象更改上下文对象的执行算法。

在模板模式中,抽象类公开定义的执行其方法的方式/模板。其子类可以根据需要重写方法实现,但调用方式必须与抽象类定义的方式相同。此模式属于行为型模式。

在访问者模式中,我们使用一个访问者类来更改元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者的变化而变化。此模式属于行为型模式。根据该模式,元素对象必须接受访问者对象,以便访问者对象处理元素对象的操作。

MVC模式代表模型-视图-控制器模式。此模式用于分离应用程序的关注点。

  • 模型 - 模型表示携带数据的对象或JAVA POJO。如果其数据更改,它还可以具有更新控制器的逻辑。

  • 视图 - 视图表示模型包含的数据的可视化。

  • 控制器 - 控制器作用于模型和视图。它控制数据流入模型对象,并在数据更改时更新视图。它使视图和模型保持分离。

业务委托模式用于解耦表示层和业务层。它基本上用于减少表示层代码中对业务层代码的通信或远程查找功能。在业务层中,我们有以下实体。

  • 客户端 - 表示层代码可以是JSP、servlet或UI java代码。

  • 业务委托 - 客户端实体的单一入口点类,用于访问业务服务方法。

  • 查找服务 - 查找服务对象负责获取相关的业务实现并将业务对象访问提供给业务委托对象。

  • 业务服务 - 业务服务接口。具体类实现此业务服务以提供实际的业务实现逻辑。

组合实体模式用于EJB持久化机制。组合实体是一个EJB实体bean,它表示对象的图形。当更新组合实体时,内部依赖对象bean会自动更新,因为它们由EJB实体bean管理。以下是组合实体bean中的参与者。

  • 组合实体 - 它是主要的实体bean。它可以是粗粒度的,也可以包含粗粒度的对象,用于持久化目的。

  • 粗粒度对象 - 此对象包含依赖对象。它有自己的生命周期,也管理依赖对象的生命周期。

  • 依赖对象 - 依赖对象是一个依赖于粗粒度对象来实现其持久化生命周期的对象。

  • 策略 - 策略表示如何实现组合实体。

数据访问对象模式或DAO模式用于将低级数据访问API或操作与高级业务服务分离。以下是数据访问对象模式中的参与者。

  • 数据访问对象接口 - 此接口定义要对模型对象执行的标准操作。

  • 数据访问对象具体类 - 此类实现上述接口。此类负责从数据源获取数据,数据源可以是数据库/xml或任何其他存储机制。

  • 模型对象或值对象 - 此对象是简单的POJO,包含用于存储使用DAO类检索的数据的get/set方法。

前端控制器设计模式用于提供集中式请求处理机制,以便所有请求都由单个处理程序处理。此处理程序可以执行请求的身份验证/授权/日志记录或跟踪,然后将请求传递给相应的处理程序。以下是这种设计模式的实体。

  • 前端控制器 - 应用程序接收的所有类型请求(基于Web/基于桌面的)的单个处理程序。

  • 调度程序 - 前端控制器可以使用调度程序对象,该对象可以将请求调度到相应的特定处理程序。

  • 视图 - 视图是发出请求的对象。

当我们希望对应用程序的请求或响应进行一些预处理/后处理时,使用拦截过滤器设计模式。在将请求传递到实际的目标应用程序之前,定义并应用过滤器。过滤器可以执行请求的身份验证/授权/日志记录或跟踪,然后将请求传递给相应的处理程序。

以下是这种设计模式的实体。

  • 过滤器 - 在请求处理程序执行请求之前或之后执行某些任务的过滤器。

  • 过滤器链 - 过滤器链承载多个过滤器,并帮助按定义的顺序在目标上执行它们。

  • 目标 - 目标对象是请求处理程序。

  • 过滤器管理器 - 过滤器管理器管理过滤器和过滤器链。

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

当我们希望使用JNDI查找来定位各种服务时,使用服务定位器设计模式。考虑到查找服务的JNDI成本很高,服务定位器模式利用缓存技术。第一次需要服务时,服务定位器在JNDI中查找并缓存服务对象。通过服务定位器进一步查找或相同服务在其缓存中进行,这在很大程度上提高了应用程序的性能。

当我们希望一次性将具有多个属性的数据从客户端传递到服务器时,使用传输对象模式。传输对象也称为值对象。传输对象是一个简单的POJO类,具有getter/setter方法并且是可序列化的,以便它可以跨网络传输。它没有任何行为。服务器端业务类通常从数据库中获取数据并填充POJO并将其发送到客户端或按值传递它。对于客户端,传输对象是只读的。客户端可以创建自己的传输对象并将其传递到服务器,以便一次性更新数据库中的值。以下是这种设计模式的实体。

  • 业务对象 - 业务服务使用数据填充传输对象。

  • 传输对象 - 只有设置/获取属性的方法的简单POJO。

  • 客户端 - 客户端向业务对象请求或发送传输对象。

下一步是什么?

接下来,您可以回顾一下您过去完成的作业,并确保您能够自信地谈论它们。如果您是应届毕业生,面试官并不期望您能够回答非常复杂的问题,而是您必须使自己的基础概念非常扎实。

其次,如果您无法回答一些问题,这实际上并不重要,重要的是,无论您回答了什么,都必须自信地回答。所以面试时要有自信。Tutorialspoint祝您能遇到一位好面试官,并祝您未来的事业一切顺利。干杯 :-)

广告
© . All rights reserved.