单一职责原则(SRP)
定义:系统中的每一个类都应该只有一个职责。
好处:高内聚、低耦合。
解释说明:
单一职责也就是说我们应该让一个类或一个对象只做一件事情,每个类所要关注的就是自己要完成的职责是什么,能够引起这个类变化的原因也应该只有一个,这也是后面提到的所有的设计模式都会遵守的一个原则。
高内聚:先按照面向对象的封装特性来理解,封装也就是我们说的,应该把一个类或对象它所有相关的属性、方法、行为放到一起,放到一个类中,这样就实现了一个封装的特性。那么内聚,就是一个类里面应该包含它所有的属性和行为。封装就是内聚的一种表现方式。高内聚是指我们一个类的属性和行为应该和这个类非常紧密,我们才把它放到这个类里面,反之我们就不应该把这个属性或行为放到这个类里面。
低耦合:内聚是指类的内部,耦合是指类与类之间或者模块之间相互的联系,这种联系、关系叫耦合,衡量这种耦合的程度,可以用耦合度来表示,耦合度越高说明类与类之间的联系是越紧密的,也就是相互之间的独立性比较差,也就是一个类必须依靠另外一个类才有意义,才能存在。耦合度越低,越容易重用,类也比较灵活。
错误案例1:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 单一职责_SRP_ 8 { 9 /// <summary> 10 /// 会计类 11 /// </summary> 12 public class Accountant 13 { 14 /// <summary> 15 /// 计算工资 16 /// </summary> 17 public void CalculateSalary() 18 { 19 // 计算工资 20 } 21 22 /// <summary> 23 /// 存储数据 24 /// </summary> 25 public void Store() 26 { 27 // 存储数据 28 } 29 } 30 }
在上面的代码中定义了一个会计类,类里面有两个方法:计算工资和存储数据。一个类里面有两个职责,并且引起这个类变化的原因有很多种:一个是计算工资的方法的参数的变化会影响类的变化,存储数据的方法的变化也会影响类的变化,没有很好的实现单一职责原则,应该把计算工资和存储数据分开。
错误案例2:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Data.SqlClient; 7 using System.Data; 8 9 namespace 单一职责_SRP_ 10 { 11 public interface IDao 12 { 13 // 获取数据库连接 14 SqlConnection GetConnection(); 15 // 关闭连接 16 void Close(); 17 // 执行添加、更新、删除操作 18 void ExecuteUpdate(string strSQL); 19 // 执行查询操作 20 DataSet ExecuteQuery(String strSQL); 21 } 22 }
上面的代码中定义了一个数据访问类,里面有两个方法:数据链接、执行增删改查的操作。数据链接一般和配置文件关联比较大。如果配置文件没有配置好、或者数据库服务没有开启,那么数据库链接可能就打不开。执行增删改查主要和SQL语句有关系。最理想的设计应该是把与数据链接有关的操作封装成一个类,把执行增删改查的操作封装到另外一个类中。
在上面的两个错误案例中,一个类都实现了两个职责,而不是一个职责,不符合单一职责的原则。这样设计类不是最完美的,建议按照单一职责的原则细分成两个类,这样就能实现高内聚低耦合。