里氏替换原则(Liskov Substitution Principle, LSP):所有引用父类的地方必须能使用其子类的对象。
怎么理解?
class A {
}
class B extends A{
}
class C {
// void func(A a) {
//
// }
//以上使用了A 类, 那必须要保证,保证什么呢? 保证替换成以下代码, 在任何情况下, 不会导致func的功能发生任何变化,不会产生任何影响
void func(B b) {
}
}
这就是里氏替换原则
只有当子类可以替换掉父类, 软件单位的功能不受到影响时,父类才能真正被复用, 而子类也能够在父类的基础上增加新的行为。
正是由于子类型的可替换性才使得使用父类类型的模块在无需修改的情况下就可以扩展、不然还谈什么扩展开放, 修改关闭呢。 再回过头来看依赖倒置原则, 高层模块不应该依赖低层模块, 两个都应该依赖抽象,也就更容易理解了。
依赖倒置其实就是谁也不依靠谁, 除了约定的接口, 大家都可以灵活自如。
当一个软件系统强耦合组成太多了, 就会面临各种问题, 如果完全面对对象来设计, 那么当出现问题的时候 排查和维护也就更容易的多。
class A {
int func(int a, int b) {
return a + b;
}
}
class B extends A{
// 这里重写了 父类A中的方法 func
int func(int a, int b) {
return a - b;
}
}
class C {
// 实现一个加法的方法
int sum(int a, int b) {
return (new A()).func(a, b);
}
}
那么要符合里氏替换原则 , 子类应该可以完全替代父类的作用, 而且不产生任何副作用
那么我们将C类中的方法进行替换处理 new A() -----> new B()
class A {
int func(int a, int b) {
return a + b;
}
}
class B extends A{
// 这里重写了 父类A中的方法 func , 变成了减法
int func(int a, int b) {
return a - b;
}
}
class C {
// 实现一个加法的方法
// int sum(int a, int b) {
// return (new A()).func(a, b);
// }
int sum(int a, int b) {
return (new B()).func(a, b);
}
}
乍一看, 完全错误了啊, 我要的是加法, 现在怎么变成减法了, 所以此时不符合里氏替换原则
如何改成符合 里氏替换原则???
思路:
思路1 就不演示了
思路2 我使用聚合关系来解决
class A {
int func(int a, int b) {
return a + b;
}
}
class B {
private A a = new A(); // B类组合A
int func(int a, int b) {
return a - b;
}
int func2(int a, int b){
return this.a.func(a, b);
}
}
class C {
//
int sum(int a, int b) {
return (new B()).func2(a, b);
}
}
此时问题通过组合关系, 解决了之前的问题, A与B