当前位置:首页 > 科技  > 软件

单一职责到底是什么?十分钟带你掌握!

来源: 责编: 时间:2024-07-02 17:36:16 78观看
导读在日常开发工作中,经常会听到有经验的技术念叨xxx需要注意单一职责,那么,什么是单一职责?如何做才能保证职责单一?这篇文章帮你分析透。什么是单一职责?关于单一职责,看过很多版本的解释,这里归纳最常见的三个版本:版本一:一个

在日常开发工作中,经常会听到有经验的技术念叨xxx需要注意单一职责,那么,什么是单一职责?如何做才能保证职责单一?这篇文章帮你分析透。7OM28资讯网——每日最新资讯28at.com

7OM28资讯网——每日最新资讯28at.com

什么是单一职责?

关于单一职责,看过很多版本的解释,这里归纳最常见的三个版本:7OM28资讯网——每日最新资讯28at.com

  • 版本一:一个类只有一个引起变化的原因
  • 版本二:一个类都应该只负责一项职责
  • 版本三:一个类只能干一件事情

哪个版本的解释比较合理呢?7OM28资讯网——每日最新资讯28at.com

单一职责原则,英文是:Single responsibility principle(SRP),是 Robert C. Martin提出的 SOLID原则中的一种,所以,我们先看看 作者对单一职责原则的描述,这里摘取了作者关于单一职责的原文:7OM28资讯网——每日最新资讯28at.com

The Single Responsibility Principle (SRP) states thateach software module should have one and only one reason to change.

原文翻译为:单一职责原则指出,任何一个软件模块都应该有一个且只有一个修改的理由。7OM28资讯网——每日最新资讯28at.com

定义看起来很严谨,但似乎和现实是相冲突的,因为软件设计本身就是一门关注长期变化的学问,变化是软件中最常见不过的问题,在现实环境中,软件系统为了满足用户和所有者的要求,势必会作出各种修改,而系统的用户或者所有者就是该设计原则所指的"被修改的原因"。7OM28资讯网——每日最新资讯28at.com

于是乎,作者又重新把单一职责描述为:7OM28资讯网——每日最新资讯28at.com

The single responsibility principle states that every moduleor class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class.

原文翻译为:单一职责原则指出,每个模块或类应该只负责软件所提供功能的一部分,并且这个职责应该完全被该类封装。7OM28资讯网——每日最新资讯28at.com

在这个定义中,每个模块或者类只负责软件的一部分功能,那这一部分是多少呢?这部分功能是否可以包含不同类型的行为呢?比如,电商中的订单和物流都可以叫做电商的一部分功能,但是他们在业务意义上显然是不同的领域,因此,该定义缺乏了定性。7OM28资讯网——每日最新资讯28at.com

于是乎,作者再次修改了单一职责的定义:7OM28资讯网——每日最新资讯28at.com

Each module should only be responsible to one actor.

原文翻译为:任何一个软件模块都应该只对某一类行为者负责7OM28资讯网——每日最新资讯28at.com

这个定义,只要是能归结成一类的行为,都可以属于某个模块的功能,这样定义看起来更符合现实业务的语意。7OM28资讯网——每日最新资讯28at.com

软件模块是什么?

在上述单一职责几个定义中都提到了软件模块,那么,软件模块到底是什么呢?7OM28资讯网——每日最新资讯28at.com

软件模块(Software Module)是指软件系统中的一个独立单元,它包含一组相关的功能和数据,这些模块是通过封装数据和功能来实现的,以便实现更高的代码复用性、可维护性和可扩展性。通常具有以下特点:7OM28资讯网——每日最新资讯28at.com

  • 独立性:模块是相对独立的代码单元,可以单独开发、测试和部署。模块的独立性提高了系统的灵活性,使得各个模块可以独立演化和更新,而不影响其他模块。
  • 封装性:模块内部的数据和实现细节对外界隐藏,只通过公开的接口与其他模块进行交互。封装性提高了代码的安全性和可维护性。
  • 职责单一:每个模块通常只负责一组相关的功能,这有助于遵循单一职责原则,使得模块更加易于理解和维护。
  • 可重用性:模块设计得当,可以在不同的项目中重复使用,提高了开发效率和代码质量。
  • 可替换性:模块通过标准化的接口与外界交互,可以在不影响其他部分的前提下替换或更新某个模块。

为了更好地说明软件模块,这里以一个电商系统为例,它可能包含以下几个模块:7OM28资讯网——每日最新资讯28at.com

(1) 用户管理模块:7OM28资讯网——每日最新资讯28at.com

  • 功能:处理用户的注册、登录、个人信息管理等。
  • 接口:提供用户注册、登录、信息更新等服务。

(2) 订单管理模块:7OM28资讯网——每日最新资讯28at.com

  • 功能:处理订单的创建、更新、查询等。
  • 接口:提供订单创建、订单状态更新、订单查询等服务。

(3) 支付处理模块:7OM28资讯网——每日最新资讯28at.com

  • 功能:处理订单的支付、退款等。
  • 接口:提供支付请求、支付状态查询、退款等服务。

(4) 库存管理模块:7OM28资讯网——每日最新资讯28at.com

  • 功能:处理商品的库存查询、更新等。
  • 接口:提供库存查询、库存更新等服务。

单一职责示例

为了更好的说明任何一个软件模块都应该只对某一类行为者负责这个定义,下面我们通过2个 Java反例来进行演示。7OM28资讯网——每日最新资讯28at.com

反例1

假设有一个 Employee员工类并且包含以下 3个方法:7OM28资讯网——每日最新资讯28at.com

public class Employee {   // calculatePay() 实现计算员工薪酬  public Money calculatePay();  // save() 将Employee对象管理的数据存储到企业数据库中  public void save();  // postEvent() 用于促销活动发布  public void postEvent();}

刚看上去,这个类设计得还挺符合实际业务,员工有计算薪酬、保存数据、发布促销等行为,但是这 3个方法对应三类不同的行为者,计算薪酬属于财务的行为,保存数据属于数据管理员的行为,发布促销属于销售的行为。7OM28资讯网——每日最新资讯28at.com

因此,Employee类将三类行为耦合在一起,违反了单一职责原则。假如一个普通员工不小心调用了calculatePay()方法,把每个员工的薪酬计算成了实际工资的2位,那可想而知这是一个灾难性的问题。7OM28资讯网——每日最新资讯28at.com

如果增加新需求,要求员工能够导出报表,因此,需要在 Employee类中增加了一个新的方法,代码如下:7OM28资讯网——每日最新资讯28at.com

// 导出报表void exportReport();

接着需求又一个一个增加,Employee类就得一次一次的变动,这会导致什么结果呢?7OM28资讯网——每日最新资讯28at.com

一方面,Employee类会不断地膨胀;另一方面,可能业务需求完全不同,却始终需要在同一个 Employee类上改动,合理吗?7OM28资讯网——每日最新资讯28at.com

联想一下你的日常开发,是否也有这样的设计?把很多不同的行为都耦合到同一个类中,然后随着业务的增加,该类急剧膨胀,最后无法维护。7OM28资讯网——每日最新资讯28at.com

该如何解决这种问题呢?7OM28资讯网——每日最新资讯28at.com

解决这个问题的方法有很多,特定的行为只能由特定的行为者来操作,因此,需要把 Employee类拆解成 3种行为者(财务、数据管理员、销售),Employee类拆分之后的代码如下:7OM28资讯网——每日最新资讯28at.com

// 财务行为public class FinanceStaff {  public Money calculatePay();}// 数据管理员行为public class TechnicalStaff {    public void save();}// 销售行为public class OperatorStaff {    public String postEvent();}

反例2

假设需要开发一个电商系统,其中有一个 Order订单类,负责处理订单的创建、订单的支付以及订单的通知,代码如下:7OM28资讯网——每日最新资讯28at.com

public class Order {    public void createOrder() {        // 订单创建逻辑    }    public void processPayment() {        // 支付处理逻辑    }    public void sendNotification() {        // 发送通知逻辑    }}

在上述代码中,Order类同时承担了订单创建、支付处理和通知发送的职责,违反了单一职责原则,因为一个类有多个引起变化的原因。7OM28资讯网——每日最新资讯28at.com

为了遵循SRP,我们需要将不同的职责分离到不同的类中,因此可以创建三个类:Order类负责订单创建,PaymentProcessor类负责支付处理,NotificationService类负责通知发送,每个类都只承担一个职责,从而遵循了单一职责原则。代码如下:7OM28资讯网——每日最新资讯28at.com

public class Order {    public void createOrder() {        // 订单创建逻辑    }}public class PaymentProcessor {    public void processPayment(Order order) {        // 支付处理逻辑    }}public class NotificationService {    public void sendNotification(Order order) {        // 发送通知逻辑    }}

上面2个示例代码的拆分都遵从了原则:因相同原因而发生变化的事物聚集在一起,因不同原因而改变的事物分开。这就是单一职责的真正体现,也是定义内聚和耦合的一种方式。7OM28资讯网——每日最新资讯28at.com

总结

从作者 Robert C. Martin对单一职责的 3次定义变更,我们可以看出:7OM28资讯网——每日最新资讯28at.com

  • 单一职责原则本质上就是要理解分离关注点。
  • 单一职责原则可以应用于不同的层次,小到一个函数,大到一个系统。
  • 软件设计也不可能一成不变。

回归到实际的工作中,我们可以把一个系统模块看作一个单一职责的行为者,比如:订单系统只关注订单相关的行为,交易系统只关注交易相关的行为,我们也可以把类作为一个单一职责的行为者,比如:订单类,把订单相关的 CRUD聚合在一起,支付类,把支付相关的信息聚合在一起。7OM28资讯网——每日最新资讯28at.com

因此,任何一个软件模块都应该只对某一类行为者负责这个定义才更适合单一职责。7OM28资讯网——每日最新资讯28at.com

最后,单一职责原则是面向对象设计的重要原则之一,它可以提高代码的可维护性、可读性和可扩展性,在日常开发中,遵循 SRP可以有效地降低类之间的耦合度,提高系统的稳定性和灵活性,从而写出更高质量的代码。7OM28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-98188-0.html单一职责到底是什么?十分钟带你掌握!

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: Python一个非常实用的库:Typer

下一篇: 一网打尽:12 个 find() 函数在 Python 中的创意实践

标签:
  • 热门焦点
  • 摸鱼心法第一章——和配置文件说拜拜

    摸鱼心法第一章——和配置文件说拜拜

    为了能摸鱼我们团队做了容器化,但是带来的问题是服务配置文件很麻烦,然后大家在群里进行了“亲切友好”的沟通图片图片图片图片对比就对比,简单对比下独立配置中心和k8s作为配
  • Automa-通过连接块来自动化你的浏览器

    Automa-通过连接块来自动化你的浏览器

    1、前言通过浏览器插件可实现自动化脚本的录制与编写,具有代表性的工具就是:Selenium IDE、Katalon Recorder,对于简单的业务来说可快速实现自动化的上手工作。Selenium IDEKat
  • Golang 中的 io 包详解:组合接口

    Golang 中的 io 包详解:组合接口

    io.ReadWriter// ReadWriter is the interface that groups the basic Read and Write methods.type ReadWriter interface { Reader Writer}是对Reader和Writer接口的组合,
  • K8S | Service服务发现

    K8S | Service服务发现

    一、背景在微服务架构中,这里以开发环境「Dev」为基础来描述,在K8S集群中通常会开放:路由网关、注册中心、配置中心等相关服务,可以被集群外部访问;图片对于测试「Tes」环境或者
  • 一年经验在二线城市面试后端的经验分享

    一年经验在二线城市面试后端的经验分享

    忠告这篇文章只适合2年内工作经验、甚至没有工作经验的朋友阅读。如果你是2年以上工作经验,请果断划走,对你没啥帮助~主人公这篇文章内容来自 「升职加薪」星球星友 的投稿,坐
  • Java NIO内存映射文件:提高文件读写效率的优秀实践!

    Java NIO内存映射文件:提高文件读写效率的优秀实践!

    Java的NIO库提供了内存映射文件的支持,它可以将文件映射到内存中,从而可以更快地读取和写入文件数据。本文将对Java内存映射文件进行详细的介绍和演示。内存映射文件概述内存
  • WebRTC.Net库开发进阶,教你实现屏幕共享和多路复用!

    WebRTC.Net库开发进阶,教你实现屏幕共享和多路复用!

    WebRTC.Net库:让你的应用更亲民友好,实现视频通话无痛接入! 除了基本用法外,还有一些进阶用法可以更好地利用该库。自定义 STUN/TURN 服务器配置WebRTC.Net 默认使用 Google 的
  • 电视息屏休眠仍有网络上传 爱奇艺被质疑“薅消费者羊毛”

    电视息屏休眠仍有网络上传 爱奇艺被质疑“薅消费者羊毛”

    记者丨宁晓敏 见习生丨汗青出品丨鳌头财经(theSankei) 前不久,爱奇艺发布了一份亮眼的一季报,不仅营收和会员营收创造历史最佳表现,其运营利润也连续6个月实现增长。自去年年初
  • iQOO 11S或7月上市:搭载“鸡血版”骁龙8Gen2 史上最强5G Soc

    iQOO 11S或7月上市:搭载“鸡血版”骁龙8Gen2 史上最强5G Soc

    去年底,iQOO推出了“电竞旗舰”iQOO 11系列,作为一款性能强机,iQOO 11不仅全球首发2K 144Hz E6全感屏,搭载了第二代骁龙8平台及144Hz电竞屏,同时在快充
Top