里氏替换原则(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)要求两个类之间尽可能保持最小的联系。










