
在线 Java 面试刷题(持续更新):https://www.quanxiaoha.com/java-interview
目录
-
面试考察点
-
核心答案
-
深度解析
-
总结
面试考察点
当面试官询问设计模式的基本原则时,他们的核心考察点并不仅仅是让你背诵七个名字,而是希望你:
-
理解设计模式的灵魂:考察你是否明白所有设计模式背后共通的设计哲学和指导思想,而不仅仅是死记硬背 23 种模式的实现。
-
评估代码设计能力 :通过你对原则的理解,判断你在日常编码中是否具备写出高内聚、低耦合、易复用、易扩展代码的意识和能力。
-
考察知识体系完整性:确认你对面向对象设计(OOD)的核心思想有系统性的认知,这些原则是 OOD 的基石。
-
探究实践与理论的结合:面试官不仅仅想知道"是什么",更想知道你能否举例说明如何运用这些原则解决实际问题,以及违反原则会导致什么后果。
核心答案
设计模式的七大基本原则,也称为 SOLID + 2 原则,是指导我们进行高质量软件设计的核心思想。它们分别是:
-
单一职责原则 (Single Responsibility Principle, SRP) :一个类只应有一个引起它变化的原因。
-
开闭原则 (Open-Closed Principle, OCP) :软件实体(类、模块、函数)应该对扩展开放,对修改关闭。
-
里氏替换原则 (Liskov Substitution Principle, LSP) :所有引用基类的地方必须能透明地使用其子类的对象,而程序的行为不会发生改变。
-
接口隔离原则 (Interface Segregation Principle, ISP) :客户端不应该被迫依赖它不使用的接口。一个类对另一个类的依赖应该建立在最小的接口上。
-
依赖倒置原则 (Dependency Inversion Principle, DIP) :高层模块不应依赖低层模块,二者都应依赖其抽象。抽象不应依赖细节,细节应依赖抽象。
-
迪米特法则 (Law of Demeter, LoD),又称最少知识原则 :一个对象应该对其他对象保持最少的了解。只与直接的朋友通信。
-
合成复用原则 (Composite Reuse Principle, CRP) :尽量使用对象组合(has-a)/聚合(contains-a),而不是继承(is-a)关系来达到复用的目的。
深度解析
这些原则共同的目标是构建可维护、可复用、灵活且健壮的软件系统。
单一职责原则 (SRP)
-
核心:一个类只负责一项职责。如果类承担了过多职责,那么任何一个职责的变化都可能影响该类,导致脆弱的设计。
-
示例 :一个
UserService类,如果同时负责用户信息持久化(saveToDB)和发送通知邮件(sendEmail),就违反了 SRP。应将持久化和邮件服务拆分为两个独立的类,UserService仅负责业务逻辑协调。 -
最佳实践:在微服务架构中,一个服务的边界定义正是 SRP 的宏观体现。
开闭原则 (OCP)
-
核心 :通过抽象 和多态来实现。当需求变化时,我们通过增加新的代码(如新的子类、实现类)来扩展功能,而非修改现有的、稳定的代码。
-
代码示例:
go
// 抽象:对扩展开放
interface DiscountStrategy {
double apply(double price);
}
// 具体实现:可以不断扩展
class VIPDiscount implements DiscountStrategy {
@Override
public double apply(double price) {
return price * 0.8;
}
}
class FestivalDiscount implements DiscountStrategy {
@Override
public double apply(double price) {
return price - 50;
}
}
class Order {
private DiscountStrategy strategy; // 依赖抽象
public void setStrategy(DiscountStrategy strategy) {
this.strategy = strategy;
}
public double calculateFinalPrice(double originalPrice) {
return strategy.apply(originalPrice); // 使用抽象
}
}
- 常见误区:OCP 不是绝对的,100% 的关闭不可能。应关注于识别出最有可能变化的区域,并为之设计稳定的抽象。
里氏替换原则 (LSP)
-
核心:它是对继承关系的严格约束。子类可以扩展父类的功能,但不能改变父类原有的功能(行为)。
-
经典反例 :
Square继承Rectangle。Rectangle有setWidth和setHeight方法,但Square的这两个方法会相互影响,改变了父类"长宽可独立设置"的行为约定,导致在使用父类Rectangle的地方替换为Square会出现错误。 -
实践:在重写方法时,子类的前置条件(对输入的要求)不能比父类更严格,后置条件(对输出的承诺)不能比父类更宽松。
接口隔离原则 (ISP)
-
核心:避免 "胖接口"。将庞大的接口拆分为更小、更具体的接口,让客户端只需知道它们关心的方法。
-
示例 :一个
Animal接口定义了eat(),fly(),swim()方法。对于Dog类来说,实现fly()是毫无意义的"接口污染"。应拆分为Eatable,Flyable,Swimmable等多个接口。
依赖倒置原则 (DIP)
-
核心 :它是实现松耦合的关键。程序的依赖关系应从"具体"倒置为"抽象"。
-
对比 :传统自上而下的设计是:高层模块
Application-> 依赖 -> 中层模块Logger-> 依赖 -> 低层模块FileWriter。倒置后:Application依赖Logger接口,FileLogger(实现类)和DatabaseLogger(实现类)也依赖同一个Logger接口。控制权从低层(FileWriter)转移到了高层(Application)。 -
框架体现 :Spring 框架的控制反转(IoC) 和依赖注入(DI) 是 DIP 原则的完美实践。我们只依赖
@Service、@Repository这样的抽象,由容器提供具体实例。
迪米特法则 (LoD)
-
核心:降低类之间的耦合度。一个类应该尽量减少对其他类内部结构的了解。
-
"朋友" 定义:出现在成员变量、方法参数、方法返回值中的类称为直接朋友。出现在方法内部的局部变量中的类不是直接朋友。
-
反例 :
A.getB().getC().doSomething()这就是典型的 "链式调用",A对C产生了依赖,耦合度变高。更好的方式可能是由B提供一个代理方法。
合成复用原则 (CRP)
-
核心 :继承是白箱复用 (破坏封装性),组合/聚合是黑箱复用(保持封装性)。
-
优势:组合关系比继承关系更灵活。可以在运行时动态改变行为(通过注入不同的组件),避免了继承体系的无限膨胀和僵化。
-
示例 :
Car类不应该继承Engine类("车是一个引擎"?这说不通),而应该组合一个Engine实例("车有一个引擎")。
总结
七大设计原则是构建优秀软件的导航图,其核心共同点在于通过抽象和中间层来隔离变化、降低耦合 ,其中**依赖倒置(DIP)**是许多原则(如开闭原则、里氏替换)能够实现的关键架构保障。在实际项目中,应灵活运用这些原则,而非教条地遵循,最终目标是交付易于维护和扩展的高质量代码。
👉 欢迎加入小哈的星球,你将获得: **专属的项目实战(多个项目) / 1v1 提问 / **Java 学习路线 /学习打卡 / 每月赠书 / 社群讨论
-
新项目:《Spring AI 项目实战》正在更新中..., 基于 Spring AI + Spring Boot 3.x + JDK 21;
-
《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍;演示地址:http://116.62.199.48:7070/
-
《从零手撸:前后端分离博客项目(全栈开发)》 2期已完结,演示链接:http://116.62.199.48/;
截止目前,累计输出 100w+ 字,讲解图 4013+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有4200+小伙伴加入



```
`1. 我的私密学习小圈子,从0到1手撸企业实战项目~
2. SpringBoot 4 最被低估的新特性:Spring Data AOT
3. 面试官:什么是 Java 序列化与反序列化?
4. Elasticsearch 写入性能排查"五板斧"`
```
`最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:点"在看",关注公众号并回复 Java 领取,更多内容陆续奉上。``PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下"在看",加个"星标",这样每次新文章推送才会第一时间出现在你的订阅列表里。
点"在看"支持小哈呀,谢谢啦`