设计模式六大原则 - 实践

news/2025/9/25 18:03:42/文章来源:https://www.cnblogs.com/ljbguanli/p/19111702

设计模式六大原则 - 实践

设计模式的六大原则,也称为SOLID这些原则的具体实现。就是原则,是面向对象设计中五个基本原则的统称。它们是构建可维护、可扩展、灵活软件的基础。很多设计模式都

第六个原则常被认为是迪米特法则,它是对前五个原则的关键补充。

下面我将逐一详细解释这六大原则。


1. 单一职责原则 (Single Responsibility Principle - SRP)

核心思想:一个类只应该有一个引起它变化的原因。换句话说,一个类应该只负责一项职责。

通俗理解:专注一件事,并把这件事做好。不要设计“万能类”。

为什么重要

  • 降低复杂性:一个类只负责一件事,其代码量自然更少,逻辑更清晰,更容易理解和维护。

  • 提高可维护性:当需要修改某个功能时,我们只需要修改负责该功能的类,不会影响到其他不相关的功能。

  • 降低变更风险:修改一个单一职责的类,对系统其他部分造成意想不到的副作用的风险更低。

示例

  • 违反SRP:一个 User 类,既包含用户属性(如 name, email),又包含将用户数据保存到数据库的方法 saveToDatabase(),还包含打印用户报告的方法 printReport()

  • 遵循SRP:将 User 类拆分为:

    • User:纯数据模型,只包含属性和基本的访问方法。

    • UserRepository:负责用户数据的持久化操作(如 save, findById)。

    • UserReportPrinter:负责打印用户相关的报告。


2. 开闭原则 (Open/Closed Principle - OCP)

核心思想:软件实体(类、模块、函数等)应该对扩展开放,但对修改关闭。

通俗理解修改已有的、已经工作正常的代码。就是:当需要添加新功能时,应该通过添加新的代码来建立,而不

为什么重要

  • 稳定性:已有的、经过测试的代码不会被修改,从而保证了系统的稳定性。

  • 可扩展性:通过继承、组合、多态等方式,可能轻松地扩展平台的行为。

如何实现:通常通过抽象化多态来实现。定义稳定的抽象接口(对修改关闭),具体的实现细节则可能借助创建新的建立类来改变和扩展(对扩展开放)。

示例

  • 有一个 Shape 类和一个计算总面积的方法 calculateTotalArea(Shape[] shapes)

  • 违反OCP:如果添加一个新的图形(如三角形),就需要修改 calculateTotalArea 方法,在里面添加 if (shape instanceof Triangle) 的判断逻辑。

  • 遵循OCP:定义一个抽象类或接口 Shape,其中有一个抽象方法 calculateArea()。让 Circle, Rectangle, Triangle 等都实现这个接口。calculateTotalArea 方法只需遍历数组并调用每个元素的 calculateArea() 方法即可,无需知道具体的图形类型。添加新图形时,只需创建新类实现 Shape 接口,而无需修改 calculateTotalArea 方法。


3. 里氏替换原则 (Liskov Substitution Principle - LSP)

核心思想:所有引用基类(父类)的地方必须能透明地采用其子类的对象,而程序的行为不会发生变化。

通俗理解:子类可能扩展父类的功能,但不能改变父类原有的功能。子类必须完全实现父类的方式,并且行为要与父类的预期保持一致。

为什么重要

  • 它是对继承关系的约束,确保继承被正确使用。

  • 保证了多态性的正确性。如果子类行为与父类不一致,那么多态替换时就会出现意想不到的错误。

示例

  • 违反LSPRectangle 类有 setWidthsetHeight 方法。你创建了一个子类 Square(正方形),重写了 setter 方法,使得设置 width 时自动将 height 设为相同值,反之亦然。这看起来合理,但从行为上看,Square 已经改变了 Rectangle 的行为。如果一个函数期望 Rectanglewidthheight 可以独立设置,传入 Square 就会导致错误。

  • 遵循LSPSquare 不应继承 Rectangle。它们可以有共同的父类 Shape,但不应有直接的继承关系,因为它们在行为上并不一致。


4. 接口隔离原则 (Interface Separation Principle - ISP)

核心思想:客户端不应该被迫依赖于它不启用的接口。一个类对另一个类的依赖应该建立在最小的接口上。

通俗理解:不要制造“臃肿”的大接口,应该根据客户端的需求,将大接口拆分成更小、更具体的接口。

为什么重要

  • 避免实现类被迫实现一些它们根本用不到的方法(通常只能空实现或抛出异常)。

  • 减少接口之间的耦合,提高系统的灵活性。

示例

  • 违反ISP:一个巨大的 Animal 接口,包含了 eat(), fly(), swim() 等方法。那么 Bird 类需要实现 swim()(可能空实现),Fish 类需要实现 fly()(空实现),Dog 类需要实现 fly()swim()(可能空实现)。

  • 遵循ISP:将 Animal 拆分为 Eater, Flyer, Swimmer 等多个精细的接口。Bird 类实现 EaterFlyerFish 类实现 EaterSwimmerDog 类可以实现 EaterSwimmer。这样每个类都只依赖于它需要的方法。


5. 依赖倒置原则 (Dependence Inversion Principle - DIP)

核心思想

  1. 高层模块不应该依赖低层模块,二者都应该依赖于抽象。

  2. 抽象不应该依赖于细节,细节应该依赖于抽象。

通俗理解:要面向接口编程,而不是面向实现编程。依据抽象(接口或抽象类)使各个类或模块彼此独立,互不依赖。

为什么重要

  • 降低耦合:高层和低层模块都依赖于抽象,从而解耦。

  • 提高可测试性:很容易通过 Mock 实现(依赖注入)来进行单元测试。

  • 提高灵活性:更换低层模块(例如从 MySQL 数据库换到 Oracle 数据库)不会影响高层模块。

示例

  • 违反DIPBook 类直接依赖于具体的 MySQLDatabase 类,在其方法中 new MySQLDatabase().save(data)

  • 遵循DIP

    1. 定义一个抽象接口 Database,包含 save 方法。

    2. MySQLDatabaseOracleDatabase 都实现 Database 接口。

    3. Book 类只依赖于 Database 接口。具体的 MySQLDatabaseOracleDatabase 实例通过构造函数Setter方法(这就是依赖注入)传递给 Book 类。


6. 迪米特法则 (Law of Demeter - LoD) / 最少知识原则

核心思想:一个对象应该对其他对象有最少的了解。只与你的直接朋友通信,不和陌生人说话。

通俗理解:一个类应该只和以下“朋友”交流:

  1. 当前对象本身 (this)

  2. 以参数形式传入到当前对象方式中的对象

  3. 当前对象的成员对象

  4. 要是成员对象是一个集合,那么集合中的元素也是朋友

  5. 当前对象所创建的对象

不要出现类似 a.getB().getC().doSomething() 这样的“链式”调用,这意味着当前对象对 abc 都有了解,耦合度太高。

为什么重要

  • 降低类之间的耦合,提高模块的独立性。

  • 使得系统更具可维护性和可扩展性。

示例

  • 违反LoDCustomer 类中有一个 Wallet wallet 属性。在商店 Shop 类中,有方法直接调用 customer.wallet.getMoney() 来获取顾客钱包里的钱。这意味着 Shop 类需要了解 Customer 的内部结构(它有一个 Wallet)以及 Wallet 的内部方法(getMoney)。

  • 遵循LoD:在 Customer 类中提供一个方法,如 public float getPayment(float amount)Shop 类只调用 customer.getPayment(100)。至于顾客是从钱包、手机还是银行卡付钱,Shop 类完全不需要知道。这样就切断了 ShopWallet 之间的直接联系。


总结

原则英文核心思想关键词
单一职责原则SRP一个类只干一件事职责单一
开闭原则OCP对扩展开放,对修改关闭抽象、多态
里氏替换原则LSP子类必须能替换父类继承、行为一致
接口隔离原则ISP接口要小而专,不要大而全精细接口
依赖倒置原则DIP面向接口编程,而非实现抽象、依赖注入
迪米特法则LoD只和直接的朋友说话减少耦合、最少知识

这六大原则是编写高质量代码的指导思想,理解和运用它们能极大地提升你的软件设计能力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/917342.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

徐霞客的《青云志》

徐霞客的《青云志》明代著名的旅行家和地理学家徐霞客的《青云志》在网络上炒得火爆。全文是: “身处低谷不自弃,我命由我不由天。 无人扶我青云志,我自踏雪至山巅。 若是命中无此运,亦可孤身登昆仑。 红尘赠我三尺…

深入解析:豆包Seedream 4.0:全面测评、玩法探索与Prompt解读

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

运营商 API 安全最佳实践、案例与方案推荐(2025)|千万级接口的全链路实战

在 5G、云原生与边缘协同的现实架构里,运营商的 API 安全应遵循一条清晰主线:资产可视 → 行为基线 → 联动处置 → 可审计证据。落地层面需要可度量、可复核的硬指标作为抓手,例如 分钟级增量捕获、告警≤0.5s、MT…

HyperWorks许可与多用户支持

在工程项目中,软件许可管理和多用户支持是确保团队协作顺畅进行的核心要素。HyperWorks作为一款领先的工程仿真软件,不仅提供了灵活的许可管理方案,还具备卓越的多用户支持功能,助力团队高效协作,共创卓越成果。 …

免费素材库短视频素材网站如何做网站知乎

大家都知道光模块是影响整个网络性能的关键因素,特别是在工业以太网中,网络连接控制的多为大型工业设备,光模块的稳定性尤为重要,那么,我们该如何选购工业级光模块呢?接下来就由飞畅科技的小编来为大家详细…

破局与进化:火山引擎Data Agent从落地实践到架构未来

本文为火山引擎技术专家陈硕,在AICon全球人工智能与机器学习技术大会上的演讲分享。本文围绕以下五部分展开:Data Agent整体介绍 智能分析Agent产品演进 智能分析Agent技术架构演进 智能分析Agent落地新进展 Data Ag…

建立网站平台做ppt的软件怎么下载网站

文章目录 写在前面Tag题目来源解题思路方法一:链表转数组方法二:自顶向下归并排序方法三:自底向上的归并排序 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更…… 专栏内…

使用trace进行排查网络瓶颈

func NewHTTPTraceLogger(ctx context.Context, fileUrl string, fragmentID, attempt int) context.Context {traceStart := time.Now()var dnsStart, connectStart, tlsStart, gotConnTime time.Timetrace := &h…

五项能力斩获满分!天翼云云WAF获IDC权威认可!

近日,国际数据公司(IDC)发布《协同大模型防火墙能力的中国WAAP厂商技术能力评估,2025》报告,围绕Web安全、Bot管理、威胁情报等核心现代应用防护需求,对厂商的产品技术与服务能力展开全面考察。天翼云云WAF产品在…

什么样的代码可以称得上是好代码? - 浪矢

目录 好代码不仅需满足功能需求,还要考虑未来的拓展,问题的排查,用户的体验和成本控制。 在Code Review & 开发行为规范中我从代码开发与实现规范,异常处理规范,日志管理规范以及版本控制与写作规范四个维度梳…

抖胆代理商,DD3118S芯片,USB3.0读卡方案,替代GL3213S方案

抖胆代理商,DD3118S芯片,USB3.0读卡方案,替代GL3213S方案DD3118s是抖胆科技推出的一款读卡器控制芯片,DD3118S基于40nm低功耗工艺设计,集成了USB 3.0、SD 3.0和eMMC 4.5协议支持能力。其最大特点是创新性地采用了…

JavaEE 导读与环境配置 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

深圳 响应式网站建设广州网站推广哪家强

在C中,函数参数的传递方式主要有三种:值传递、引用传递和指针传递。下面我会分别解释这三种方式的区别: 值传递(Pass by Value): 值传递是将实际参数的值复制给函数的形式参数。这意味着函数接收的是原始数据的一个副本…

中宁网站建设公司网页美工设计中职期末试卷

【漏洞详情】 漏洞描述:Alibaba Nacos derby 存在远程代码执行漏洞,由于Alibaba Nacos部分版本中derby数据库默认可以未授权访问,恶意攻击者利用此漏洞可以未授权执行SQL语句,从而远程加载恶意构造的jar包,最终导致任意…

南昌网站排名ui设计师的工作内容是什么

为当前组件添加内容模糊效果。 说明: 从API Version 10开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 foregroundBlurStyle foregroundBlurStyle(value: BlurStyle, options?: ForegroundBlurStyleOptions) 为当前组件提供…

番禺网站建设优化推广wordpress 离线编辑器

Scrum作为一种敏捷开发方法,具有许多优势,但也面临一些挑战。以下是Scrum的主要优势和挑战: Scrum优势: 快速交付价值: Scrum采用迭代开发方法,每个Sprint周期结束时交付一个可用的增量,使团队…

如何在腾讯云上建设网站wordpress分类目录修改

这段代码是一个简单的文件读取和写入的例子。它创建了一个BufferFile类,构造方法接受一个文件名作为参数。BufferFile类中的write方法用于从标准输入读取内容,并将其写入到指定的文件中,直到输入"end"为止。read方法用于读取指定文…

微软Teams Channel Agent上线:中国卖家AI赋能品牌出海新机遇与实战策略(2025前瞻) - 详解

微软Teams Channel Agent上线:中国卖家AI赋能品牌出海新机遇与实战策略(2025前瞻) - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !impor…

docker制作

安装完docker后,在dockerfile路径下运行:docker build --rm -t flask_app:v1 ./--rm作用:构建过程中自动删除临时创建的中间容器。 说明:Docker 构建镜像时会生成多个中间层容器,--rm 可以避免这些临时容器占用磁…

做好网站如何发布wordpress主题放在

文章目录 一. 训练Keras中的MNIST数据集二. 工作流程1. 构建神经网络2. 准备图像数据3. 训练模型4. 利用模型进行预测5. (新数据上)评估模型精度 本节将首先给出一个神经网络示例,引出如下概念。了解完本节后,可以对神经网络在代码上的实现有一个整体的了…