跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

Java 设计模式核心七大原则实战解析

Java 设计模式七大原则是构建高质量软件的基础,涵盖开闭、依赖倒置、单一职责等核心概念。文章结合 4S 店销售业务案例,解析如何通过抽象、接口隔离及组合复用优化代码结构。旨在帮助开发者在复杂多变场景中平衡扩展性与维护成本,避免过度设计,实现更稳健的系统架构。

氛围发布于 2019/9/28更新于 2026/10/1173 浏览
Java 设计模式核心七大原则实战解析

前言

确实,没有设计模式也能完成开发。但为什么还需要它们?为了代码的层次感、可读性以及维护性。面对复杂多变的业务场景,尤其是要求高适配性和扩展性的地方,设计模式能提供成熟的解决方案。当然,不要为了用而用,简单稳定的业务不必强求。

接下来结合实际案例探讨一下设计模式的一些原则。

1. 开闭原则

public class Seller {
    public BigDecimal sellCar(Car car) {
        return car.getPrice();
    }
}

上面模拟了 4S 店销售卖车。假设老板突然搞促销:双十一打折。如果在 sellCar 方法内直接增加计算逻辑,势必影响整个业务,导致所有车都打折,且后续活动结束或升级时还需反复改动。如果直接在 Car 类里操作,各种逻辑判断会让代码臃肿不堪。

对于复杂多变的业务,设计模式能解决上述问题。最重要的原则就是开闭原则(Open-Closed Principle):软件实体如类、模块和函数应该对扩展开放,对修改关闭。我们需要将业务行为抽象出来,使用抽象构建,具体业务通过实现来解决。

例如,创建一个 DiscountCar 继承自 Car,这样 sellCar 执行什么逻辑就取决于具体的实现,不会影响原有逻辑,保证接口可靠性和稳定性。

public class DiscountCar extends Car {
    private BigDecimal price;
    private BigDecimal discount;

    @Override
    public BigDecimal getPrice() {
        return price.multiply(discount);
    }
}

2. 依赖倒置原则

经过一系列活动,老板想扩展周边业务,让销售同时卖玻璃水、防冻液等。需求抛给程序员后,如果一直增加 sellGlassWater、sellAntifreeze 等方法,未来卖大米、鸡蛋饼怎么办?

我们需要抽象所有卖东西的场景。把卖的物品抽象成概念(Java 中对应接口),把卖的行为抽象成 sell 方法。

public interface Any {
    String getName();
    BigDecimal getPrice();
}

public class Seller {
    public BigDecimal sell(Any any) {
        return any.getPrice();
    }
}

这样无论以后卖什么,都可以通过该方法处理,只需关注 Any 的实现。

3. 单一职责原则

销售发现单纯卖车吸引力不大,老板又提出新要求:销售还要会唱、跳、Rap。人与人能力不同,有的只会唱,有的全能。为了适配这种情况,必须把每种技能独立出来,根据不同的人组合这些技能。

public class Seller implements Sing, Jump, Rap {
    public BigDecimal sell(Any any) {
        return any.doSell();
    }

    @Override
    public void sing() {
        System.out.println("seller sing");
    }

    @Override
    public void jump() {
        System.out.println("seller jumping");
    }

    @Override
    public void rap() {
        System.out.println("seller raping");
    }
}

注意一定要适度,根据业务细分。否则会导致接口过多,反而增大开发难度和代码复杂度。

4. 迪米特法则

老板想看报表检验效果。程序员可能这么写:

public class Boss {
    private Seller seller;
    private Report report;

    public void read() {
        seller.apply(report);
    }
}

乍看功能实现了,细看逻辑不对。老板已经持有了报表,如果老板直接知道了业绩还叫销售干什么?这种逻辑肯定是不对的。也就是说 Boss 直接依赖了 Report,而这个 Report 不应该由 Boss 直接处理,应由 Seller 控制。

public class Boss {
    private Seller seller;

    public void read() {
        seller.apply();
    }
}

public class Seller {
    private Report report;

    public void apply() {
        report.show();
    }
}

这种写法最大化隔离了类与类之间的关系,降低了耦合度。迪米特法则因此又得名最少知道原则。

5. 接口隔离原则

用多个专门的接口,而不使用单一的总接口。客户端不应该依赖它不需要的接口。一个类对一个类的依赖应该建立在最小的接口上。

建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,方法尽量少。注意适度原则,不能滥用。就像上面的唱跳 Rap,分离是最好的。

6. 里氏代换原则

主要针对类的继承关系。正式定义是:如果对每一个类型为 S 的对象 o1,都有类型为 T 的对象 o2,使得以 T 定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 S 是类型 T 的子类型。

在 4S 店老板眼里,只要新来的能在销售岗位上像老手一样卖出汽车,他就是一名合格的销售。这就像那句名言:不管黑猫白猫,能抓老鼠的都是好猫。

从某种含义上,里氏代换有着以下契约:

  1. 子类必须完全实现父类的方法。父类出现的地方子类都可以代替父类。
  2. 子类可以有自己的个性定义。里氏替换原则可以正着用,但是不能反过来用。在子类出现的地方,父类未必就可以胜任。子类一般比父类有个性。
  3. 覆盖或实现父类的方法时输入参数可以被放大。如果老板规定基础车谈价折扣最多九折,销售打个九五折没问题,打八折老板肯定要跟你说道说道了。
  4. 覆写或实现父类的方法时输出结果可以被缩小。同样是 15W 本来只能卖出乞丐版,结果换了个销售给出旗舰版,怕不是过不了试用期哦。

7. 合成/复用原则

它要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。

如果要使用继承关系,则必须严格遵循里氏替换原则。合成复用原则同里氏替换原则相辅相成,两者都是开闭原则的具体实现规范。

总结

这七种设计原则是软件设计模式必须尽量遵循的原则,各种原则要求的侧重点不同。其中,开闭原则是总纲,告诉我们要对扩展开放,对修改关闭;里氏替换原则告诉我们不要破坏继承体系;依赖倒置原则告诉我们要面向接口编程;单一职责原则告诉我们实现类要职责单一;接口隔离原则告诉我们在设计接口的时候要精简单一;迪米特法则告诉我们要降低耦合度;合成复用原则告诉我们要优先使用组合或者聚合关系复用,少用继承关系复用。在实际开发中我们可以根据业务来进行设计模式的使用,但是很重要的一点千万不要被这些条条框框束缚了你的手脚。

目录

  1. 前言
  2. 1. 开闭原则
  3. 2. 依赖倒置原则
  4. 3. 单一职责原则
  5. 4. 迪米特法则
  6. 5. 接口隔离原则
  7. 6. 里氏代换原则
  8. 7. 合成/复用原则
  9. 总结

更多推荐文章

查看全部
  • React + Ant Design 登录界面 UI 美化实战
  • 零基础黑客入门:普通人成为安全专家的十个步骤
  • Spring Boot Web 三大核心交互案例:表单、AJAX 及 JSON
  • 2026 年主流 AI 生成 PPT 工具实测与横向对比
  • Figma Make 实测:AI 辅助前端开发的可行性分析
  • Java 在 AI 时代的演进:从机器学习到 AIGC 实战
  • 中小团队基于 Ubuntu 的 DooTask 项目管理系统私有化部署实战
  • Enterprise Architect 16 中文版入门:从零绘制 UML 用例图
  • Quick-Logger-Colorful:轻量无依赖的 Python 彩色日志库,同步异步双支持
  • OpenWebUI 联网搜索实战:用 SearXNG 让本地大模型获取实时信息
  • Kotaemon:基于 RAG 技术的多语言模型问答系统
  • 开源知识库 RAGFlow 从部署到实战操作详解
  • LangChain4j 集成多模型 Provider 方案:OpenAI 与本地模型混合部署
  • OpenClaw 浏览器控制方案:利用 Chrome Debug 模式实现全自动控制
  • 光伏产品缺陷检测 AI 深度学习算法
  • Copilot 的 agent、ask、edit、plan 模式区别
  • Copilot Plan Mode 与多模型协同实战:复杂项目开发实践
  • 国内 10 家主流 AI 大模型盘点与特性分析
  • C++ string 类详解与模拟实现
  • KWDB 运维实战:用 SQL 打通 Metrics 与 CMDB

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online