浅谈C#六大设计原则

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

里氏替换原则(LSP:Liskov Substitution Principle)要求:凡是父类出现的地方,子类都可以出现。

这就要求了子类必须与父类具有相同的行为。只有当子类能够替换任何父类的实例时,才会符合里氏替换原则。

里氏替换原则的约束:

1  子类必须实现父类的抽象方法,但不能重写父类中已实现的方法。

2  子类中可以增加方法拓展功能。

3  当子类覆盖或实现(虚拟方法/抽象方法)父类的方法时,方法的输入参数限制更加宽松并且返回值要比父类方法更加严格。

所以,我们看到开闭原则中的示例,子类应不应该重载父类的方法?应不应该使用 new 关键字隐藏父类的方法?为了确保子类继承后,还具有跟父类一致的特性,不建议这样做呢,亲。

实现了开闭原则,自然可以使用里氏替换原则。

依赖倒置原则

依赖倒置原则(Dependence Inversion Principle)要求程序要依赖于抽象接口,不要依赖于具体实现。

我们可以从代码中,慢慢演进和推导理论。

 // 实现登录注销
 public class UserLogin
 {
  public void Login(){}
  public void Logout(){}
 }

 public class Test1 : UserLogin { }

 public class Test2
 {
  private readonly UserLogin userLogin = new UserLogin();
 }

 public class Test3
 {
  private readonly UserLogin _userLogin;
  public Test3(UserLogin userLogin)
  {
   _userLogin = userLogin;
  }
 }

上面代码中,Test1、Test2、Test3 都依赖 UserLogin 。先不说上面代码有什么毛病,根据依赖倒置原则,应该是这样编写代码的

 // 与登录有关
 public interface IUserLogin
 {
  void Login();  // 登录
  void Logout();  // 注销
 }

 // 实现登录注销
 public class UserLogin1 : IUserLogin
 {
  public void Login(){}
  public void Logout(){}
 }
 
 // 实现登录注销
 public class UserLogin2 : IUserLogin
 {
  public void Login(){}
  public void Logout(){}
 }

 public class Test4
 {
  private readonly IUserLogin _userLogin;
  public Test4(IUserLogin userLogin)
  {
   _userLogin = userLogin;
  }
 }

依赖倒置原则,在于引入一种抽象,这种抽象将高级模块和底层模块彼此分离。高层模块和底层模块松耦合,底层模块的变动不需要高层模块也要变动。

依赖导致原则有两个思想:

1  高层模块不应该依赖于底层模块,两者都应该依赖于抽象。

2  抽象不应该依赖细节,细节应该依赖于抽象。

因为依赖于抽象,底层模块可以任意替换一个实现了抽象的模块。

里氏替换原则是要求子类父类行为一致,子类可以替换父类。

依赖倒置原则,每个方法的行为是可以完全不一样的。

迪米特法则

迪米特法则(Law of Demeter)要求两个类之间尽可能保持最小的联系。