【秋招必备】设计模式面试题(2021最新版)
前言
设计模式在日常的工作中,是非常重要的一项技能,使用设计模式可以重构整体架构代码、提交代码复用性、扩展性、减少代码冗余问题。这是每个 Java 工程师必备的技能!今日小编主要讲的是设计模式之一的策略模式,小编会通过案例和面试题,带你一步步由浅入深对策略模式进行解析。
小编分享的这份Java后端开发面试总结包含了JavaOOP、Java集合容器、Java异常、并发编程、Java反射、Java序列化、JVM、Redis、Spring MVC、MyBatis、MySQL数据库、消息中间件MQ、Dubbo、Linux、ZooKeeper、 分布式&数据结构与算法等26个专题技术点,都是小编在各个大厂总结出来的面试真题,已经有很多粉丝靠这份PDF拿下众多大厂的offer,今天在这里总结分享给到大家!【已完结】
完整版Java面试题地址:2021最新面试题合集集锦。
1.什么是设计模式
设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
2.为什么要学习设计模式
- 看懂源代码:如果你不懂设计模式去看Jdk、Spring、SpringMVC、IO等等等等的源码,你会很迷茫,你会寸步难行
- 看看前辈的代码:你去个公司难道都是新项目让你接手?很有可能是接盘的,前辈的开发难道不用设计模式?
- 编写自己的理想中的好代码:我个人反正是这样的,对于我自己开发的项目我会很认真,我对他比对我女朋友还好,把项目当成自己的儿子一样
3.设计模式分类

4.设计模式的六大原则
- 开放封闭原则(Open Close Principle)

- 里氏代换原则(Liskov Substitution Principle)

- 依赖倒转原则(Dependence Inversion Principle)

- 接口隔离原则(Interface Segregation Principle)

- 迪米特法则(最少知道原则)(Demeter Principle)

- 单一职责原则(Principle of single responsibility)

5.单例模式
5.1 什么是单例
保证一个类只有一个实例,并且提供一个访问该全局访问点
5.2 哪些地方用到了单例模式
- 网站的计数器,一般也是采用单例模式实现,否则难以同步。
- 应用程序的日志应用,一般都是单例模式实现,只有一个实例去操作才好,否则内容不好追加显示。
- 多线程的线程池的设计一般也是采用单例模式,因为线程池要方便对池中的线程进行控制
- Windows的(任务管理器)就是很典型的单例模式,他不能打开俩个
- windows的(回收站)也是典型的单例应用。在整个系统运行过程中,回收站只维护一个实例。
5.3 单例优缺点

5.4 单例模式使用注意事项:
- 使用时不能用反射模式创建单例,否则会实例化一个新的对象
- 使用懒单例模式时注意线程安全问题
- 饿单例模式和懒单例模式构造方法都是私有的,因而是不能被继承的,有些单例模式可以被继承(如登记式模式)
5.5 单例防止反射漏洞攻击
private static boolean flag = false;
private Singleton() {
if (flag == false) {
flag = !flag;
} else {
throw new RuntimeException("单例模式被侵犯!");
}
}
public static void main(String[] args) {
}
5.6 如何选择单例创建方式
如果不需要延迟加载单例,可以使用枚举或者饿汉式,相对来说枚举性好于饿汉式。 如果需要延 迟加载,可以使用静态内部类或者懒汉式,相对来说静态内部类好于懒韩式。 最好使用饿汉式
5.7 单例创建方式

1.饿汉式
- 饿汉式:类初始化时,会立即加载该对象,线程天生安全,调用效率高。
package com.lijie;
//饿汉式
public class Demo1 {
// 类初始化时,会立即加载该对象,线程安全,调用效率高
private static Demo1 demo1 = new Demo1();
private Demo1() {
System.out.println("私有Demo1构造参数初始化");
}
public static Demo1 getInstance() {
return demo1;
}
public static void main(String[] args) {
Demo1 s1 = Demo1.getInstance();
Demo1 s2 = Demo1.getInstance();
System.out.println(s1 == s2);
}
}




6.工厂模式
6.1 什么是工厂模式
它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。实现了创建者和调用者分离,工厂模式分为简单工厂、工厂方法、抽象工厂模式
6.2 工厂模式好处
- 工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。
- 利用工厂模式可以降低程序的耦合性,为后期的维护修改提供了很大的便利。
- 将选择实现类、创建对象统一管理和控制。从而将调用者跟我们的实现类解耦。
6.3 为什么要学习工厂设计模式
不知道你们面试题问到过源码没有,你知道Spring的源码吗,MyBatis的源码吗,等等等 如果你想学习很多框架的源码,或者你想自己开发自己的框架,就必须先掌握设计模式(工厂设计模式用的是非常非常广泛的)
6.4 Spring开发中的工厂设计模式

6.5 工厂模式分类









7.代理模式
7.1 什么是代理模式
- 通过代理控制对象的访问,可以在这个对象调用方法之前、调用方法之后去处理/添加新的功能。(也就是AO的P微实现)
- 代理在原有代码乃至原业务流程都不修改的情况下,直接在业务流程中切入新代码,增加新功能,这也和Spring的(面向切面编程)很相似
7.2 代理模式应用场景
Spring AOP、日志打印、异常处理、事务控制、权限控制等
7.3 代理的分类
- 静态代理(静态定义代理类)
- 动态代理(动态生成代理类,也称为Jdk自带动态代理)
- Cglib 、javaassist(字节码操作库)
7.4 三种代理的区别
1.静态代理:简单代理模式,是动态代理的理论基础。常见使用在代理模式
- jdk动态代理:使用反射完成代理。需要有顶层接口才能使用,常见是mybatis的mapper文件是代理。
- cglib动态代理:也是使用反射完成代理,可以直接代理类(jdk动态代理不行),使用字节码技术,不能对 fifinal类进行继承。(需要导入jar包)
7.5 用代码演示三种代理
7.5.1静态代理
什么是静态代理
由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。









8.建造者模式
8.1 什么是建造者模式
- 建造者模式:是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的方 式进行创建。
- 工厂类模式是提供的是创建单个类的产品
- 而建造者模式则是将各种产品集中起来进行管理,用来具有不同的属性的产品

8.2 建造者模式的使用场景

8.3 代码案例



9.模板方法模式
9.1 什么是模板方法
模板方法模式:定义一个操作中的算法骨架(父类),而将一些步骤延迟到子类中。 模板方法使得子类可以不改变一个算法的结构来重定义该算法的
9.2 什么时候使用模板方法
实现一些操作时,整体步骤很固定,但是呢。就是其中一小部分需要改变,这时候可以使用模板方法模式,将容易变的部分抽象出来,供子类实现。
9.3 实际开发中应用场景哪里用到了模板方法
- 其实很多框架中都有用到了模板方法模式
- 例如:数据库访问的封装、Junit单元测试、servlet中关于doGet/doPost方法的调用等等
9.4 现实生活中的模板方法

9.5 代码实现模板方法模式



10.外观模式
10.1 什么是外观模式
- 外观模式:也叫门面模式,隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。
- 它向现有的系统添加一个接口,用这一个接口来隐藏实际的系统的复杂性。
- 使用外观模式,他外部看起来就是一个接口,其实他的内部有很多复杂的接口已经被实现
10.2 外观模式例子




11.原型模式
11.1 什么是原型模式
- 原型设计模式简单来说就是克隆
- 原型表明了有一个样板实例,这个原型是可定制的。原型模式多用于创建复杂的或者构造耗时的实 例,因为这种情况下,复制一个已经存在的实例可使程序运行更高效。
11.2 原型模式的应用场景

11.3 原型模式的使用方式

11.4 代码演示


12.策略模式
12.1 什么是策略模式
- 定义了一系列的算法 或 逻辑 或 相同意义的操作,并将每一个算法、逻辑、操作封装起来,而且使它们还可以相互替换。(其实策略模式Java中用的非常非常广泛)
- 我觉得主要是为了 简化 if...else 所带来的复杂和难以维护
12.2 策略模式应用场景

12.3 策略模式的优点和缺点
优点:
1、算法可以自由切换。
2、避免使用多重条件判断。
3、扩展性非常良好。
缺点:
1、策略类会增多。
2、所有策略类都需要对外暴露。
12.4 代码演示
模拟支付模块有微信支付、支付宝支付、银联支付
- 定义抽象的公共方法



13.观察者模式
13.1 什么是观察者模式
- 先讲什么是行为性模型,行为型模式关注的是系统中对象之间的相互交互,解决系统在运行时对象之间的相互通信和协作,进一步明确对象的职责。
- 观察者模式,是一种行为性模型,又叫发布-订阅模式,他定义对象之间一种一对多的依赖关系,使得当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
13.2 模式的职责
观察者模式主要用于1对N的通知。当一个对象的状态变化时,他需要及时告知一系列对象,令他们做出相应。
实现有两种方式:
- 推:每次都会把通知以广播的方式发送给所有观察者,所有的观察者只能被动接收。
- 拉:观察者只要知道有情况即可,至于什么时候获取内容,获取什么内容,都可以自主决定。
13.3 观察者模式应用场景
- 关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。事件多级触发场景。
- 跨系统的消息交换场景,如消息队列、事件总线的处理机制。
13.4 代码实现观察者模式




【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)