浅谈C#六大设计原则

2020-06-10 19:00:36于海丽

笔者作为一个菜鸟,会尝试以简单的代码和容易理解的语句去解释这几种原则的特性和应用场景。

这六种原则分别为单一职责原则、接口隔离原则、里氏替换原则、迪米特法则、依赖倒置原则、开闭原则。

单一职责原则

单一职责原则(SRP:Single responsibility principle),规定一个类中应该只有一个原因引起类的变化。

单一职责原则的核心就是解耦和增强内聚性。

问题:

 // 假设此类是数据库上下文
 public class DatabaseContext { }

 public class Test
 {
  private readonly DatabaseContext _context;
  public Test(DatabaseContext context)
  {
   _context = context;
  }

  // 用户登录
  public void UserLogin() { }

  // 用户注销
  public void UserLogout() { }

  // 新增一个用户
  public void AddUser() { }

  // 修改一个用户的信息
  public void UpdateUser() { }

  // 删除一个用户
  public void DeleteUser() { }
 }

Test 负责 职责 P1(用户登录和退出)和 P2(用户账号管理) 两个职责,当由于职责 P1 的需求发生变化而需要修改类时, 有可能会导致正常职责 P2 的功能发生故障。

上面的代码中,两个职责被耦合起来,担任了多种功能。

一个类中应该只有一个原因引起类的变化,也就要求一个类只应该负责一个功能,类中地代码是紧密联系的。

上面的示例代码非常简单,我们可以很自然地将一个个类分为两个部分。

 // 假设此类是数据库上下文
 public class DatabaseContext { }

 public class Test1
 {
  private readonly DatabaseContext _context;
  public Test1(DatabaseContext context)
  {
   _context = context;
  }

  // 用户登录
  public void UserLogin() { }

  // 用户注销
  public void UserLogout() { }

 }

 public class Test2
 {
  private readonly DatabaseContext _context;
  public Test2(DatabaseContext context)
  {
   _context = context;
  }
  // 新增一个用户
  public void AddUser() { }

  // 修改一个用户的信息
  public void UpdateUser() { }

  // 删除一个用户
  public void DeleteUser() { }
 }

因此,单一职责原则的解决方法,是将不同职责封装到不同的类或模块中。

接口隔离原则

接口隔离原则(ISP:Interface Segregation Principle) 要求对接口进行细分,类的继承建立在最小的粒度上,确保客户端继承的接口中,每一个方法都是它需要的。

笔者查阅了国外一些资料,大多将接口隔离原则定义为:

“Clients should not be forced to depend upon interfaces that they do not use.”

意思是不应强迫客户依赖于它不使用的方法。

对于此原则的解释,这篇文章讲的非常透彻:

https://stackify.com/interface-segregation-principle/

这就要求我们拆分臃肿的接口成为更小的和更具体的接口,使得接口负责的功能更加单一。