tulip notes
首页
  • 学习笔记

    • 《Vue》
  • 踩坑日记

    • JavaScript
  • MQ
  • Nginx
  • IdentityServer
  • Redis
  • Linux
  • Java
  • SpringBoot
  • SpringCloud
  • MySql
  • docker
  • 算法与设计模式
  • 踩坑与提升
  • Git
  • GitHub技巧
  • Mac
  • 网络
  • 项目构建合集
  • 一些技巧
  • 面试
  • 一些杂货
  • 友情链接
  • 项目发布
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Star-Lord

希望一天成为大师的学徒
首页
  • 学习笔记

    • 《Vue》
  • 踩坑日记

    • JavaScript
  • MQ
  • Nginx
  • IdentityServer
  • Redis
  • Linux
  • Java
  • SpringBoot
  • SpringCloud
  • MySql
  • docker
  • 算法与设计模式
  • 踩坑与提升
  • Git
  • GitHub技巧
  • Mac
  • 网络
  • 项目构建合集
  • 一些技巧
  • 面试
  • 一些杂货
  • 友情链接
  • 项目发布
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Java

  • SpringBoot

  • SpringCloud

  • Mysql

  • docker

  • 算法与设计模式

    • 算法初入
    • 十大经典排序算法
    • 动态规划-1
    • 设计模式初入
    • 六大设计原则
      • 单一责任原则
      • 里氏替换原则
      • 依赖倒置原则
      • 接口隔离原则
      • 迪米特法则
      • 开闭原则
    • 单例模式与工厂模式
    • 代理模式和模版模式
    • 策略模式和观察者模式
  • 踩坑与提升

  • 后端
  • 算法与设计模式
EffectTang
2024-09-16
目录

六大设计原则

# 六大设计原则

以下六大原则,是我们要追求的标准,但实际开发中因为一些情况(为了更高效)或者其他原因,我们可能会违反它们,但我们应该尽量避免这种情况的出现,因为按照这些原则设计出来的软件,它的可维护性、健壮性更好。

# 单一责任原则

单一职责原则的定义是:应该有且仅有一个原因引起类的变更。

换句话说,一个类应该只负责一项功能或职责,并且这个职责应该是明确的、独立的。如果一个类承担了多个职责,那么当其中一个职责发生变化时,可能会对其他职责造成影响,从而增加代码的复杂性和维护难度。

假设你有一个Employee类,它负责员工的基本信息管理,如姓名、职位等,同时也负责计算员工的工资。按照单一职责原则,这样的设计并不理想,因为员工信息的变化(如更新个人信息)和工资计算的变化(如调整税率)是两种不同的需求,它们可能会独立地发生改变。

因此我们建议在设计接口时,设计成2个接口。

这样一来,就会有如下几点优势:

  • 类的复杂性降低,实现什么职责都有清晰明确的定义;
  • 可读性提高,复杂性降低;
  • 可维护性提高,可读性提高;
  • 变更引起的风险降低

当一个类承担过多的责任时,它会变得庞大而复杂,使得理解和维护变得更加困难。随着功能的不断增加,代码会越来越难以阅读和修改。此外,变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的实现类有影响,对其他的接口无影响,这对系统的扩展性、维护性都有非常大的帮助。

但请记住,单一职责原则最难划分的就是职责。一个职责一个接口,但问题是“职责”没有一个量化的标准,一个类到底要负责那些职责?这些职责该怎么细化?细化后是否都要有一个接口或类?这些都需要从实际的项目去考虑,因此单纯的追求单一原则是不可取的,要根据实际情况而定。

对于接口,我们在设计的时候一定要做到单一,但是对于实现类就需要多方面考虑了。生搬硬套单一职责原则会引起类的剧增,给维护带来非常多的麻烦,而且过分细分类的职责也会人为地增加系统的复杂性。本来一个类可以实现的行为硬要拆成两个类,然后再使用聚合或组合的方式耦合在一起,人为制造了系统的复杂性。

# 里氏替换原则

里氏替换原则的核心思想是:

子类必须能够替换其基类,并且在不修改调用者的前提下,保证程序的正确性。

简单来说,如果你有一个基类(父类)和一个继承自该基类的子类,那么在任何可以使用基类的地方,也应该能够使用子类而不会出现问题。这要求子类的行为不应该破坏基类的契约,即子类应当保持与基类相同的接口行为,而且不应改变基类的预期行为。

# 依赖倒置原则

依赖倒置原则的核心思想是:

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

简单来说,依赖倒置原则提倡依赖于接口或抽象类,而不是具体的实现类。这样做的目的是为了使代码更加灵活,易于扩展和维护。

高层模块通常是指那些专注于业务逻辑实现的模块。它们负责定义应用程序的核心功能和处理复杂的业务流程。

底层模块是指那些提供具体实现细节的模块。它们通常负责执行具体的任务或提供特定的服务。

依赖倒置原则的两个方面

  1. 高层模块与低层模块的关系:
    • 高层模块负责业务逻辑的实现,而低层模块则提供具体的实现细节。
    • 高层模块应该依赖于抽象,而不是具体的实现细节。这样即使底层实现发生变化,高层模块也不受影响。
  2. 抽象与细节的关系:
    • 抽象是指接口或抽象类,而细节是指具体的实现类。
    • 抽象不应该依赖于细节,相反,细节应该依赖于抽象。这意味着具体的实现类应该实现抽象接口或继承抽象类,而不是反过来。

在项目中,大家只要记住是“面向接口编程”就基本上抓住了依赖倒置原则的核心。

# 接口隔离原则

接口隔离原则的核心思想是:

一个类不应该被迫依赖于它不需要的方法。换句话说,客户端不应该被迫依赖于它不需要的接口中的方法。

ISP强调的是精简接口,使得类、模块或组件之间的依赖更加明确和精细。这可以通过将庞大的接口分解成更小、更具体的接口来实现,从而使实现类只需要知道并实现它真正需要的那一部分。

接口隔离原则的主要目标是提高系统的灵活性、可维护性和可扩展性。通过遵循ISP,可以达到以下目的:

  1. 减少耦合:类之间依赖的接口越少,耦合度就越低,从而提高了系统的灵活性。
  2. 提高复用性:精简的接口更容易被复用,因为它们不会包含不必要的方法。
  3. 简化设计:通过分解大的接口为多个小接口,可以简化类的设计,使每个类更加专注和独立。
  4. 易于维护:当接口更小、更具体时,修改或扩展接口变得更简单,因为影响范围更小。

# 迪米特法则

迪米特法则的核心思想是:

一个对象应该对其它对象有尽可能少的知识。

具体来说,一个类应该尽可能减少与其他类的交互。类与类之间的通信应该保持在最小限度,每个类都应该有清晰的职责边界,并且应该避免不必要的直接通信。

迪米特法则的核心观念就是类间解耦,弱耦合,只有弱耦合了以后,类的复用率才可以提高。其要求的结果就是产生了大量的中转或跳转类,导致系统的复杂性提高,同时也为维护带来了难度。读者在采用迪米特法则时需要反复权衡,既做到让结构清晰,又做到高内聚低耦合。

在实际应用中,如果一个类跳转两次以上才能访问到另一个类,就需要想办法进行重构了,为什么是两次以上呢?因为一个系统的成功不仅仅是一个标准或是原则就能够决定的,有非常多的外在因素决定,跳转次数越多,系统越复杂,维护就越困难,所以只要跳转不超过两次都是可以忍受的,这需要具体问题具体分析。

# 开闭原则

迪米特法则的核心思想是:

一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。

软件实体应该对扩展开放,对修改关闭,其含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。

上次更新: 2025/04/23, 16:23:16
设计模式初入
单例模式与工厂模式

← 设计模式初入 单例模式与工厂模式→

最近更新
01
面向切面跟自定义注解的结合
05-22
02
时间跟其他数据的序列化
05-19
03
数据加密与安全
05-17
更多文章>
Theme by Vdoing | Copyright © 2023-2025 EffectTang
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式