SHOW ME THE CODE - 面向对象程序设计之 - 单一职责原则

2024-04-23 10:28

本文主要是介绍SHOW ME THE CODE - 面向对象程序设计之 - 单一职责原则,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今天我们从代码的角度来讲一讲,到底什么是:单一职责原则

SRP的定义

Single Responsibility Principle, 单一职责原则
单一职责原则(Single Responsibility Principle,SRP)最早是由罗伯特·C·马丁(Robert C. Martin)在他的经典著作《敏捷软件开发:原则、模式与实践》(Agile Software Development: Principles, Patterns, and Practices)中提出的。这本书于2003年首次出版,其中探讨了敏捷软件开发的原则、模式和实践。

在该书中,马丁将单一职责原则描述为:“一个类应该只有一个导致它变化的原因。”这个简明的定义强调了类的内聚性和责任的单一性,表明一个类应该只负责一个明确的任务或功能,而不应该包含多个不相关的功能或责任。

怎么理解单一职责

一个类只有一个职责,也可以理解只承担一个角色。即一个类应该专注于完成一个特定的任务或者扮演一个特定的角色,而不应该包含多个不相关的职责或角色。这样可以提高类的内聚性,使得类的设计更加清晰、简洁和易于理解。

例子1:现代化的流水线

大家可以试想一下,为什么现代化的工厂都是流水线作业?一台手机,一台汽车,一台飞机,从那么多的零部件如何组件成为了消费者手上的产品?流水线上的每一个环节,可以理解了一个类,他们都只专注于一件事情。

比如,汽车制造过程中的几个重要的环节:

  • 冲压工序
  • 焊接工序
  • 涂装工序
  • 总装工序

一条现代化的生产线,最终通过流水线的作业形式,结合信息技术,将生产过程中的各个具备不同职责的工序有机的整合起来,最终形成一条完整的生产线,从而实现高效、优质、低成本地生产产品。

例子2:部队

从古至今,部队都是按不同的兵种划分,古代有骑兵,有弓箭兵,有长枪兵,有水兵,有陆兵。现代,有海、陆、空,有步兵,有坦克兵,有炮兵,有医疗兵,有航空兵,还有信息化部队,后勤部队等等。

企业的运作

现代企业需要IT系统来支撑公司的日常运营工作,而企业的运营是由不同角色的人通过各种不同的流程有机的联系在一起才能使得企业高效的运转。

使用IT系统的人,来自于企业不同的部门,承担着不同的岗们职责,而我们设计IT系统的时候,也应该和企业的组织架构保持一致。比如说,HR和财务就是不同的角色。HR负责员工信息的管理,而员工奖金的分配,则通常是财务的事情。

SHOW ME THE CODE - 年终奖的计算该放在哪里

不正确的方式 - 违反SRP原则

// 员工基本信息类
public class Employee {private String name;private int employeeId;private double salary;public Employee(String name, int employeeId, double salary) {this.name = name;this.employeeId = employeeId;this.salary = salary;}public double calculateBonus() {double bonus = 0.0;// 假设这里有一些计算年终奖金的复杂逻辑......return bonus;}
}

我们看到,Bouns的计算放在了Employee 这个类里边,这里实际上就已经违反了单一职责原则,Employee 不仅负责员工基本信息的管理,还要负责年终奖金的计算。

Employee类涉及了两类现实中的角色,HR和财务人员。
现实中HR会负责员工信息的收集和更新。而年终奖的发放通常是需要结合企业的营收,中心的绩效,部门的绩效,以及个人绩效等多方面因素来决定,具体的计算逻辑应该由财务决定,而且有一些数据,只允许财务人员才能够看。

我们员工年终的信息应该从Payroll类中获取,而具体的计算逻辑则放在年终奖计算器BonusCalculator中。

正确的方式 - 职责分离

重构后的代码应该如下,这样就不违反单一职责原则了。Enployee不会包含除了员工信息管理之外的其它职责,Bonus的计算有专门的工具类来实现。


public class Employee {private String name;private int employeeId;private double salary;public Employee(String name, int employeeId, double salary) {this.name = name;this.employeeId = employeeId;this.salary = salary;}
}public class Payroll
{private BonusCalculator bonusCalculator;public void setBonusCalculator(BonusCalculator bonusCalculator){this.bonusCalculator = bonusCalculator;}public double getBouns(Employee employee){return bonusCalculator.calculateBonus(employee);}
}public class BonusCalculator {public double calculateBonus(Employee employee) {double bonus = 0.0;// 假设这里有一些计算年终奖金的复杂逻辑......return bonus;}
}

这篇关于SHOW ME THE CODE - 面向对象程序设计之 - 单一职责原则的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/928539

相关文章

C#继承之里氏替换原则分析

《C#继承之里氏替换原则分析》:本文主要介绍C#继承之里氏替换原则,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#里氏替换原则一.概念二.语法表现三.类型检查与转换总结C#里氏替换原则一.概念里氏替换原则是面向对象设计的基本原则之一:核心思想:所有引py

JVM内存调优原则及几种JVM内存调优方法

JVM内存调优原则及几种JVM内存调优方法 1、堆大小设置。 2、回收器选择。   1、在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存,这个数值不能准确的反应堆内存的真实占用情况,因为GC过后这个值是不会变化的,因此内存调优的时候要更多地使用JDK提供的内存查看工具,比如JConsole和Java VisualVM。   2、对JVM内存的系统级的调优主要的目的是减少

C语言程序设计(数据类型、运算符与表达式)

一、C的数据类型 C语言提供的数据类型: 二、常量和变量 2.1常量和符号常量 在程序运行过程中,其值不能被改变的量称为常量。 常量区分为不同的类型: 程序中用#define(预处理器指令)命令行定义变量将代表常量,用一个标识符代表一个常量,称为符合常量。 2.2变量 变量代表内存中具有特定属性的一个存储单元,用来存放数据,在程序运行期间,这些值是可以 改变的。 变

PHP最长单一子串

<?php//方法一$s='abcccddddddcdefg';$max='';while($s!=''){$i=0; while($i<strlen($s) && $s[$i]==$s[0]) $i++;if ($i>strlen($max)){$max=substr($s,0,$i);} $s=substr($s,$i);}echo $m

C语言程序设计(选择结构程序设计)

一、关系运算符和关系表达式 1.1关系运算符及其优先次序 ①<(小于) ②<=(小于或等于) ③>(大于) ④>=(大于或等于 ) ⑤==(等于) ⑥!=(不等于) 说明: 前4个优先级相同,后2个优先级相同,关系运算符的优先级低于算术运算符,关系运算符的优先级高于赋值运算符 1.2关系表达式 用关系运算符将两个表达式(可以是算术表达式或关系表达式,逻辑表达式,赋值表达式,字符

ffmpeg面向对象-待定

1.常用对象 rtsp拉流第一步都是avformat_open_input,其入参可以看下怎么用: AVFormatContext *fmt_ctx = NULL;result = avformat_open_input(&fmt_ctx, input_filename, NULL, NULL); 其中fmt_ctx 如何分配内存的?如下 int avformat_open_input(

Debugging Lua Project created in Cocos Code IDE creates “Waiting for debugger to connect” in Win-7

转自 I Installed Cocos Code IDE and created a new Lua Project. When Debugging the Project(F11) the game window pops up and gives me the message waiting for debugger to connect and then freezes. Also a

07 v-if和v-show使用和区别

划重点: v-ifv-show 小葱拌豆腐 <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="

LLVM入门2:如何基于自己的代码生成IR-LLVM IR code generation实例介绍

概述 本节将通过一个简单的例子来介绍如何生成llvm IR,以Kaleidoscope IR中的例子为例,我们基于LLVM接口构建一个简单的编译器,实现简单的语句解析并转化为LLVM IR,生成对应的LLVM IR部分,代码如下,文件名为toy.cpp,先给出代码,后面会详细介绍每一步分代码: #include "llvm/ADT/APFloat.h"#include "llvm/ADT/S

chapter06 面向对象基础 知识点Note

文章目录 前言类的设计 属性和行为对象的内存解析 (堆 栈 方法区)类的成员之一 变量(属性) field类的成员之二 方法 method对象数组方法重载 overload可变个数的形参 语法糖方法的值传递机制递归关键字package importMVC设计模式import导入面向对象特征之一 封装类的成员之三 构造器JavaBeanUML类图 前言 ` 面向对象封装 面向