今天我们从代码的角度来讲一讲,到底什么是:单一职责原则
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;
}
}