【面向对象设计原则】之单一职责原则(SRP)
单一职责原则是面向对象原则五大原则中最简单,也是最重要的一个原则, 他的字面定义如下:
单一职责原则(Single Responsibility Principle, SRP): 一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。
从定义中可以看出在定义类的时候要将职责划分清楚, 不能让一个类负责干多个事情。换句话说就是一个类只有一个引起他变化的点。如果一个类负责干多个事情那么就会有多个引起他变化的原因。那么这个类就不稳定了,这个类就容易变化,因为我们知道如果干的事情越少变化的诱因就愈少,如果干的事情越多变化的诱因就愈多。变化的越多引起bug的可能性就越大, 最终就会影响到你设计的系统容易出现bug,反之系统出现bug的肯能性就越小。
现在我们有这么一个场景,对人员信息的维护, 通常对用数据库的操作如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Employee {
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public DateTime BirthDay { get; set; }
}
public class EmployeeRepository {
public void Create(Employee employee) {
DataBase<Employee> dataBase = new DataBase<Employee>();
dataBase.Create(employee);
}
public IEnumerable<Employee> Query() {
DataBase<Employee> dataBase = new DataBase<Employee>();
return dataBase.Query();
}
}
咋一看这个设计似乎是没有问题的,但是在看看我们刚刚讲的那个原则,其实这个设计已经违背了我么的 SRP原则
,主要是 EmployeeRepository
类的职责太多。它包含的两个方法,一个是给数据库中创建数据一个是查询数据,从这个拆分粒度上来说是 EmployeeRepository
承担了两个职责。 因此我们因该将他拆分开来如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class EmployeeRepository {
public void Create(Employee employee) {
DataBase<Employee> dataBase = new DataBase<Employee>();
dataBase.Create(employee);
}
}
public class EmployeeQuery {
public IEnumerable<Employee> Query() {
DataBase<Employee> dataBase = new DataBase<Employee>();
return dataBase.Query();
}
}
这样我们就将原来的 EmployeeRepository
中的查询数据的职责拆分到 EmployeeQuery
类中,这样 EmployeeRepository
就只负责对数据的”写”操作而 EmployeeQuery
只负责对数据”读”操作, 这就回到了计算机的本质上来了, 即计算机的本质就是 “读写”.
写到这里就应该告一段落了, 但是我想很多人都会说第一个 EmployeeRepository
的职责划分的也可以啊,只负责数据的操作啊, 其实这个问题也没有错, SRP原则本身就是一个充满争议的原则, 每个人对类的组织不同,职责的划分不同, 系统的规模不同对SRP使用也是不同, 对SRP的把握粒度也不同,这要根据具体问题具体对待.