面试官:设计模式的 7 大基本原则有哪些?

在线 Java 面试刷题(持续更新):https://www.quanxiaoha.com/java-interview

目录

  • 面试考察点

  • 核心答案

  • 深度解析

  • 总结


面试考察点

当面试官询问设计模式的基本原则时,他们的核心考察点并不仅仅是让你背诵七个名字,而是希望你:

  1. 理解设计模式的灵魂:考察你是否明白所有设计模式背后共通的设计哲学和指导思想,而不仅仅是死记硬背 23 种模式的实现。

  2. 评估代码设计能力 :通过你对原则的理解,判断你在日常编码中是否具备写出高内聚、低耦合、易复用、易扩展代码的意识和能力。

  3. 考察知识体系完整性:确认你对面向对象设计(OOD)的核心思想有系统性的认知,这些原则是 OOD 的基石。

  4. 探究实践与理论的结合:面试官不仅仅想知道"是什么",更想知道你能否举例说明如何运用这些原则解决实际问题,以及违反原则会导致什么后果。

核心答案

设计模式的七大基本原则,也称为 SOLID + 2 原则,是指导我们进行高质量软件设计的核心思想。它们分别是:

  1. 单一职责原则 (Single Responsibility Principle, SRP) :一个类只应有一个引起它变化的原因。

  2. 开闭原则 (Open-Closed Principle, OCP) :软件实体(类、模块、函数)应该对扩展开放,对修改关闭。

  3. 里氏替换原则 (Liskov Substitution Principle, LSP) :所有引用基类的地方必须能透明地使用其子类的对象,而程序的行为不会发生改变。

  4. 接口隔离原则 (Interface Segregation Principle, ISP) :客户端不应该被迫依赖它不使用的接口。一个类对另一个类的依赖应该建立在最小的接口上。

  5. 依赖倒置原则 (Dependency Inversion Principle, DIP) :高层模块不应依赖低层模块,二者都应依赖其抽象。抽象不应依赖细节,细节应依赖抽象。

  6. 迪米特法则 (Law of Demeter, LoD),又称最少知识原则 :一个对象应该对其他对象保持最少的了解。只与直接的朋友通信。

  7. 合成复用原则 (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 继承 RectangleRectanglesetWidthsetHeight 方法,但 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() 这就是典型的 "链式调用",AC 产生了依赖,耦合度变高。更好的方式可能是由 B 提供一个代理方法。

合成复用原则 (CRP)

  • 核心 :继承是白箱复用 (破坏封装性),组合/聚合是黑箱复用(保持封装性)。

  • 优势:组合关系比继承关系更灵活。可以在运行时动态改变行为(通过注入不同的组件),避免了继承体系的无限膨胀和僵化。

  • 示例Car 类不应该继承 Engine 类("车是一个引擎"?这说不通),而应该组合一个 Engine 实例("车有一个引擎")。

总结

七大设计原则是构建优秀软件的导航图,其核心共同点在于通过抽象和中间层来隔离变化、降低耦合 ,其中**依赖倒置(DIP)**是许多原则(如开闭原则、里氏替换)能够实现的关键架构保障。在实际项目中,应灵活运用这些原则,而非教条地遵循,最终目标是交付易于维护和扩展的高质量代码。

👉 欢迎加入小哈的星球,你将获得: **专属的项目实战(多个项目) / 1v1 提问 / **Java 学习路线 /学习打卡 / 每月赠书 / 社群讨论

截止目前,累计输出 100w+ 字,讲解图 4013+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有4200+小伙伴加入

复制代码
![图片](https://i-blog.csdnimg.cn/img_convert/d129da397f39e87a7bdc8e5e1fbe1a3e.gif)

```
`1. 我的私密学习小圈子,从0到1手撸企业实战项目~
2. SpringBoot 4 最被低估的新特性:Spring Data AOT
3. 面试官:什么是 Java 序列化与反序列化?
4. Elasticsearch 写入性能排查"五板斧"`

```
复制代码
`最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:点"在看",关注公众号并回复 Java 领取,更多内容陆续奉上。``PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下"在看",加个"星标",这样每次新文章推送才会第一时间出现在你的订阅列表里。
点"在看"支持小哈呀,谢谢啦`
相关推荐
chools5 小时前
一篇文章带你搞懂Java“设计模式”! - - 超长文(涵盖23种)万字总结!【汇总篇】
java·开发语言·设计模式
geovindu6 小时前
python: Null Object Pattern
开发语言·python·设计模式
数据中穿行8 小时前
单例设计模式全方位深度解析
设计模式
程序员Terry9 小时前
还在用 if-else 做兼容?三分钟学会适配器模式,让你的代码更优雅
java·设计模式
zhoupenghui16810 小时前
golang中常用的设计模式举例
设计模式
lichenyang45310 小时前
组件设计模式与通信
前端·javascript·设计模式
lichenyang45311 小时前
React 性能优化组件设计模式与通信
前端·javascript·设计模式
Kel11 小时前
这就是编程:Pi Monorepo 源码深度--解析一个工业级 AI Agent 框架的设计哲学
人工智能·设计模式·架构
geovindu11 小时前
python: Simple Factory Pattern
开发语言·python·设计模式·简单工厂模式