什么是单一职责原则 (SRP)?
单一职责原则 (SRP) 是面向对象编程 (OOP) 的五个 SOLID 原则之一。它指出一个类改变的原因不应该超过一个。一个类应该专注于单一功能。
单一职责原则是必不可少的,因为它有助于保持代码的可维护性、灵活性和易于理解。具有多重职责的类往往紧密耦合,因此很难在不影响其他职责的情况下更改一项职责。这使得代码库脆弱且难以维护。
假设您构建软件的时间较长,并且需要对其进行调整以适应持续的变更请求。您可能会觉得最简单和最快的方法是向现有代码添加方法或功能,而不是编写新类或组件。但这通常会导致类承担的责任更多,并且使维护软件变得越来越困难。您可以在进行任何更改之前通过询问一个简单的问题来避免这些问题:
你的类/组件/微服务的责任是什么?
如果您的回答包含“和”一词,您很可能违反了单一职责原则。
那么就需要重新考虑您当前的实现方式,很可能有更好的方法来实现它。例如,让我们借助代码来理解 “ SOLID 原则-单一职责原则 ”。
示例:违反单一职责原则的代码
此示例演示了违反“SOLID 原则 - 单一职责原则”的代码。
假设编写一个员工信息,并且根据员工的姓名和年龄从数据库查找的 Java 程序。我们将创建一个 Employee
类。
/**
* 员工
*/
public class Employee {
// 名字
private String name;
// 年龄
private Integer age;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
public List<Employee> searchEmployee() {
// 查找员工信息逻辑
}
上述代码违反了单一职责原则,因为 Employee
类有两个职责。
- 它设置与
Employee
相关的属性(name 和 age)。 - 它在库中搜索员工信息。 当
setter
方法更改Employee
对象,当我们想在库中搜索相同的员工信息时,这可能会导致问题。
示例#:遵循单一职责原则的代码
此示例演示了遵循 “SOLID 原则 - 单一职责原则”的代码。
为了应用“SOLID 原则-单一职责原则”,我们需要将两个职责分离。在重构后的代码中,Employee
类将只负责获取和设置 Employee
对象的属性。如下所示:
/**
* 员工
*/
public class Employee {
// 名字
private String name;
// 年龄
private Integer age;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
然后,我们创建另一个名为 RepositoryView
的类,它将负责搜索员工。我们将 searchEmployee()
方法移至此处并在构造函数中引用 Employee 类。如下所示:
public class RepositoryView {
private Employee employee;
public RepositoryView (Employee employee) {
this.employee = employee;
}
public List<Employee> searchEmployee() {
// 查找员工信息逻辑
}
在下面的 UML 图中,您可以看到我们按照单一职责原则重构代码后架构发生了怎样的变化。我们将具有两个职责的初始 Employee 类拆分为两个类,每个类都有自己的单一职责。
其它案例
- web 端:文件上传组件、导出组件等等
- 微服务: 鉴权服务、网关、用户服务等等
实体管理器
在优秀的开源项目中可以找到所有 SOLID 设计原则的大量示例。比如您使用的 Java 持久层和应用的流行框架(Mybatis 、 Hibernate …),使用这些 ORM 框架,基本都会遵循 单一职责原则。
其中之一是 Java Persistence API (JPA) 规范。它有一个,而且只有一个责任:通过使用对象-关系映射概念,定义一种标准化的方式来管理关系数据库中持久保存的数据。EntityManager 接口提供了一组方法来保存、更新、删除和读取关系数据库中的实体。 它的职责是管理与当前持久性上下文关联的实体。
如果您在 Java 的一个类中放置了多个功能,则可能会引入两个功能之间的耦合。即使您更改了一项功能,也有可能破坏了另一项功能。因此,将需要进行另一轮测试,以避免在生产环境中出现任何意外。
单一职责原则有什么好处?
让我们讨论一下这个原则如何帮助我们构建更好的软件?即它的一些好处。
-
更容易测试
具有一种职责的类将具有更少的测试用例,从而导致测试工作量大大减少。 -
松耦合
单个类中的功能越少,依赖性就越少。因此,它将降低耦合。 -
更容易读
较小的、组织良好的类比较大的类更容易被初次阅读代码的人搜索到。 -
更容易使用
与为所有功能提供解决方案的类、组件、框架、和微服务相比,只有一种职责的类、组件、框架、和微服务更容易解释、理解和实现。这减少了错误的数量,提高了开发速度,并使你作为程序员,上班摸鱼的时间大大的增加。 -
更容易维护
通过确保您的类只有一个责任,您可以节省大量开发应用程序的工作并创建更易于维护的体系结构。
总结
总之,单一职责原则是 OOP 的一个基本原则,它指出一个类应该只有一个职责。这有助于保持代码可维护、灵活且易于理解。通过应用 SRP,可以创建集中且简洁的类,这使它们更易于理解和重用。