2021年设计模式面试题大汇总附答案
2021年设计模式面试题大汇总附答案
全部面试题答案,更新日期:01月30日,直接下载吧!#
下载链接:高清500+份面试题资料及电子书,累计 10000+ 页大厂面试题 PDF#
设计模式#
题1:Java 中如何实现策略模式?
#
实例:假设张三要到北方做买卖,走之前张三的父亲给仆人三个锦囊,说是危机关头按顺序依次拆开能解决相应的问题。场景中出现三个要素:妙计(具体策略类)、锦囊(环境事件类)、仆人(调用者)。
1、抽象策略类(Strategy)
public interface Strategy {
public void operate();
}
2、妙计一,初到北方地界,实现类:
public class NorthernBoundary implements IStrategy {
@Override
public void operate() {
System.out.println("钱财打通官府,求照应,方便行事");
}
}
3、妙计二,在当地开展买卖事宜,实现类:
public class UnderstandingCustomsCulture implements IStrategy {
@Override
public void operate() {
System.out.println("了解当地风俗文化");
}
}
4、妙计三,地皮流氓闹事,官府快速接入处理,实现类:
public class AccessProcessing implements IStrategy {
@Override
public void operate() {
System.out.println("地皮流氓闹事,官府快速接入处理");
}
}
5、环境事件类(Context):
public class ContextEvent {
private Strategy strategy;
//构造函数
public ContextEvent(Strategy strategy){
this.strategy = strategy;
}
public void setStrategy(Strategy strategy){
this.strategy = strategy;
}
public void operate(){
this.strategy.operate();
}
}
6、简单测试类:
public class BlogYoodb {
public static void main(String[] args) {
ContextEvent context;
System.out.println("----------初到北方地界使用锦囊一---------------");
context = new ContextEvent(new NorthernBoundary());
context.operate();
System.out.println("\n");
System.out.println("----------开展买卖事宜使用锦囊二---------------");
context.setStrategy(new UnderstandingCustomsCulture());
context.operate();
System.out.println("\n");
System.out.println("----------地皮流氓闹事,使用锦囊三---------------");
context.setStrategy(new AccessProcessing());
context.operate();
System.out.println("\n");
}
}
题2:设计模式的六大原则是什么?
#
1)开闭原则(Open Close Principle)
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。
2)里氏代换原则(Liskov Substitution Principle)
里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
3)依赖倒转原则(Dependence Inversion Principle)
这个是开闭原则的基础,具体内容:真对接口编程,依赖于抽象而不依赖于具体。
4)接口隔离原则(Interface Segregation Principle)
大概意思是指使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。
5)迪米特法则(最少知道原则)(Demeter Principle)
为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
6)合成复用原则(Composite Reuse Principle)
原则是尽量使用合成/聚合的方式,而不是使用继承。
题3:Java 中如何实现装饰模式?
#
1、定义通用接口,代码如下:
package com.yoodb;
public interface Job {
/**
* 准备工作,以老鼠、猫、狗三种动物,做饭的小故事为例
*/
public void prepare();
}
2、老鼠工作内容,代码如下:
package com.yoodb;
public class Mouse implements Job{
@Override
public void prepare() {
// TODO Auto-generated method stub
System.out.println("老鼠用锅盛满了水.\n");
}
}
3、小猫工作内容,代码如下:
package com.yoodb;
public class Cat implements Job{
//被装饰者
private Job job;
public Cat() {}
public Cat(Job job) {
this.job = job;
}
@Override
public void prepare() {
// TODO Auto-generated method stub
//装饰者职责
System.out.println("小猫正在准备柴进行点火工作.\n");
//被装饰者职责
job.prepare();
//装饰者职责
System.out.println("小猫将锅上架并把火点着了.\n");
}
}
4、小狗工作内容,代码如下:
package com.yoodb;
public class Dag implements Job{
private Job job;
public Dag(Job job) {
this.job = job;
}
public Dag() {}
@Override
public void prepare() {
// TODO Auto-generated method stub
//装饰者做的职责
System.out.println("小狗正在做食材的准备工作\n");
///被装饰者职责
job.prepare();
//装饰者做的职责
System.out.println("小狗已把食材准备成功,放入锅中!\n");
}
}
5、测试Main,代码如下:
package com.yoodb;
public class DecoratorMain {
public static void main(String[] args) {
Job mouse = new Mouse();
mouse.prepare();
Job cat = new Cat(mouse);
cat.prepare();
Job dag = new Dag(cat);
dag.prepare();
}
}
6、输出结果如下:
老鼠用锅盛满了水.
小猫正在准备柴进行点火工作.
老鼠用锅盛满了水.
小猫将锅上架并把火点着了.
小狗正在做食材的准备工作
小猫正在准备柴进行点火工作.
老鼠用锅盛满了水.
小猫将锅上架并把火点着了.
小狗已把食材准备成功,放入锅中!
题4:微服务架构的六种常用设计模式是什么?
#
代理设计模式
聚合设计模式
链条设计模式
聚合链条设计模式
数据共享设计模式
异步消息设计模式
题5:装饰模式和适配器模式有什么区别?
#
装饰模式:对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,提供比继承更多的灵活性。使用原来被装饰的类的一个子类的实例,把客户端的调用委派到被装饰类。
适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。
从定义上看装饰模式是对核心对象或者功能的扩展,适配器模式是把对象或者功能放到一个新对象中引用。举个例子,现在书城卖道德经的书,有线装版,有精装版,有日文版,有英文版,其中线装版和精装版就是装饰模式,日文版和英文版就是适配器模式,各种版本都是为迎合不同消费者的不同需求。为什么呢?因为线装版和精装版的道德经虽然包装不同,但内容相同,日文版和英文版就不同,这两个版本的内容就可能和原版的不同,文化差异嘛,翻译的内容虽来自道德经,但根据不同国家的文化,思维逻辑什么的就可能改变一些想法。
使用条件
装饰模式一般在下列情况使用:需要扩展一个类的功能或者给你个类增加附加责任;需要动态的给一个对象增加功能,这些功能可以再动态的撤销;需要增加有一些基本功能的排列组合而产生非常大量的功能,从而使得继承关系变得不现实。
适配器模式一般使用的情况包括:系统需要使用现有的类,但此类已经不符合系统的需要;
想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的的类一起工作。适配器模式在系统升级的时候使用的频率很高,对旧系统的一些功能方法在新系统中引用。
题6:什么是设计模式?
#
设计模式(Design pattern) 是解决软件开发某些特定问题而提出的一些解决方案也可以理解成解决问题的一些思路,通过设计模式可以帮助我们增强代码的可重用性、可扩充性、 可维护性、灵活性好。使用设计模式最终的目的是实现代码的高内聚和低耦合。
高内聚低耦合是软件工程中的概念,是判断软件设计好坏的标准,主要用于程序的面向对象的设计,主要看类的内聚性是否高,耦合度是否低。
目的是使程序模块的可重用性、移植性大大增强。
通常程序结构中各模块的内聚程度越高,模块间的耦合程度就越低。
内聚是从功能角度来度量模块内的联系,一个好的内聚模块应当恰好做一件事,它描述的是模块内的功能联系;耦合是软件结构中各模块之间相互连接的一种度量,耦合强弱取决于模块间接口的复杂程度、进入或访问一个模块的点以及通过接口的数据。
题7:Java 中解释器模式有什么优点?
#
解释器模式提供了一个简单的方式来执行语法,而且容易修改或者扩展语法。
一般系统中很多类使用相似的语法,可以使用一个解释器来代替为每一个规则实现一个解释器。而且在解释器中不同的规则是由不同的类来实现的,这样使得添加一个新的语法规则变得简单。
题8:Java 中工厂方法模式有什么应用场景?
#
在以下情况下,适用于工厂方法模式:
1)当一个类不知道它所必须创建的对象的类的时候。
2)当一个类希望由它的子类来指定它所创建的对象的时候。
3)当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
题9:Java 中装饰模式有什么应用场景?
#
1、需要扩展一个类的功能。
2、动态的为一个对象增加功能,而且还能动态撤销。
题10:Java 中代理模式如何实现动态代理?
#
Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:
1)Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组;这个抽象方法在代理类中动态实现。
2)Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容:
Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。
Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。
Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。
接口(或抽象类),具体代码如下:
package com.yoodb;
public interface Business {
public void doAction();
}
此处是真正意义上实现业务逻辑的类,具体代码如下:
package com.yoodb;
public class BusinessImpl implements Business {
@Override
public void doAction() {
// TODO Auto-generated method stub
System.out.println("实现业务逻辑.");
}
}
动态代理方式,具体代码如下:
package com.yoodb;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicBusinessProxy implements InvocationHandler{
private Object obj;
public DynamicBusinessProxy() {}
public DynamicBusinessProxy(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
Object result = null;
doBefore();
result = method.invoke(obj, args);
doAfter();
return result;
}
private void doBefore(){
System.out.println("调用目标对象前做相关操作");
}
private void doAfter(){
System.out.println("调用目标对象后做相关操作");
}
public static Object factory(Object obj)
{
Class<? extends Object> cls = obj.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),new DynamicBusinessProxy(obj));
}
}
单元测试,具体代码如下:
package com.yoodb;
public class MainTest {
public static void main(String[] args) {
Business business = (Business) DynamicBusinessProxy.factory(new BusinessImpl());
business.doAction();
}
}
运行之后结果如下:
调用目标对象前做相关操作
实现业务逻辑.
调用目标对象后做相关操作
题11:单例模式都有哪些应用场景
#
题12:java-中什么是原型模式
#
题13:装饰模式和代理模式有什么区别
#
题14:java-中建造者模式有什么使用场景
#
题15:什么是单例模式
#
题16:java-中什么是模板方法模式
#
题17:java-中三种代理模式有什么区别
#
题18:什么是工厂模式
#
题19:java-中如何实现解释器模式
#
题20:java-中外观模式有什么使用场景
#
题21:java-中工厂模式有什么优势
#
题22:java-中什么是简单工厂模式
#
题23:java-中什么是策略模式
#
题24:java-中什么是解释器模式
#
题25:java-中什么是替换法则lsp
#
作者:staluo
出处:https://www.cnblogs.com/stry/p/17028465.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!