设计模式的七大原则(4) --里氏替换原则

前言

上一节中我们介绍了,依赖倒置,依赖倒置利用抽象的稳定性来架构我们的系统,是我们经常能遇到的一种原则,比如说面向接口编程。

这一节中,我们来说说里氏替换原则,这个原则其实非常非常的简单,其实与依赖倒置相结合来看,就是希望我们用抽象的方法来构建项目而非具体的实现,里氏替换原则就是推荐我们不要重写父类中具体的实现来构建我们的项目。

我们来深入研究研究。

基本介绍

  1. 继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些已经实现的方法任意修改,就会对整个继承体系造成破坏。
  2. 继承在给程序设计带来便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能产生故障

那么翻译成比较容易理解的话,就是说,子类一般不该重写父类的方法,因为父类的方法一般都是对外公布的接口,是具有不可变性的,你不该将一些不该变化的东西给修改掉。

上述只是通常意义上的说法,很多情况下,我们其实不必要太过于在意这个原则,因为相对于继承带给我们的好处,很多时候我们会忽略掉其带来的弊端。比如缺省适配器,装饰器模式等一些设计模式

不过就算如此,如果你真的遇见了不得不重写父类方法的场景,那么请你考虑,你是否真的要把这个类作为子类出现在这里,或者说这样做所换来的是否能弥补你失去的东西,比如子类无法代替父类工作,那么就意味着如果你的父类可以在某一个场景里工作的很正常,那么你的子类当然也应该可以,否则就会出现下述场景。

案例

//某一个类
public class SomeoneClass {
    //有某一个方法,使用了一个父类类型
    public void someoneMethod(Parent parent){
        parent.method();
    }
}

父类代码如下

public class Parent {

    public void method(){
        System.out.println("parent method");
    }
}

结果我有一个子类把父类的方法给覆盖了,并且抛出了一个异常。

public class SubClass extends Parent{

    //结果某一个子类重写了父类的方法,说不支持该操作了
    public void method() {
        throw new UnsupportedOperationException();
    }

}

这个异常是运行时才会产生的,也就是说,我的SomeoneClass并不知道会出现这种情况,结果就是我调用下面这段代码的时候,本来我们的思维是Parent都可以传给someoneMethod完成我的功能,我的SubClass继承了Parent,当然也可以了,但是最终这个调用会抛出异常。

public class Client {

    public static void main(String[] args) {
        SomeoneClass someoneClass = new SomeoneClass();
        someoneClass.someoneMethod(new Parent());
        someoneClass.someoneMethod(new SubClass());
    }
}

这就相当于埋下了一个个陷阱,因为本来我们的原则是,父类可以完成的地方,我用子类替代是绝对没有问题的,但是这下反了,我每次使用一个子类替换一个父类的时候,我还要担心这个子类有没有给我埋下一个上面这种炸弹。

所以里氏替换原则是一个需要我们深刻理解的原则,因为往往有时候违反它我们可以得到很多,失去一小部分,但是有时候却会相反,所以要想做到活学活用,就要深刻理解这个原则的意义所在。

总结

到这里我们已经掌握了四个原则(单一职责原则,接口隔离原则,依赖倒置原则,里氏替换原则)

下一个原则是非常非常重要的原则。甚至说,我们前面讲的都是为了下一个开闭原则做的准备也不为过。所以说掌握这四种原则是非常非常重要的。

(0)

相关推荐

  • 软件设计原则讲解,昭昭在目

    一.UML 图 不要觉得奇怪为什么不讲软件设计原则而说到了 UML 图,因为软件设计原则和软件设计模式中你讲到最多的便是利用类图来表示 类与类之间的关系,因此我们需要 先会看,再会理,最后再来写! 1 ...

  • Java无参构造方法的作用

    无参构造函数,主要用于在子类创建对象时使用,java程序在执行子类的构造方法之前,会去调用父类构造方法,可以显示的指定super()某一个父类构造函数,如未显示指定 super(), public c ...

  • 设计模式 - 七大设计原则(三)- 迪米特法则与里氏替换原则

    概述 简单介绍一下七大设计原则: 开闭原则:是所有面向对象设计的核心,对扩展开放,对修改关闭 依赖倒置原则:针对接口编程,依赖于抽象而不依赖于具体 单一职责原则:一个接口只负责一件事情,只能有一个原因 ...

  • 面向对象设计原则(SOLID原则)

    一.单一功能(single responsibility) 单一功能原则,也叫单一职责原则.简单来说,就是一个类应该只有一个引起它变化的原因,其中心思想就是面向对象设计原则中的高内聚,低耦合.当分析有 ...

  • 软件设计的六大原则剖析

    我们平时编写代码时,很少有人为了刻意迎合软件设计原则而编写.其实,有时候是你用到了其中的某个或多个设计原则,而不自知而已.也有可能是有的人压根就不知道设计原则是什么. 不过,没关系,为了搞明白既抽象又 ...

  • 面向对象六大原则

    这篇文章主要讲的是面向对象设计中,应该遵循的六大原则.只有掌握了这些原则,才能更好的理解设计模式. 我们接下来要介绍以下6个内容. 单一职责原则--SRP 开闭原则--OCP 里氏替换原则--LSP ...

  • 最简单直接地理解Java软件设计原则之里氏替换原则

    理论性知识 定义 里氏替换原则,Liskov Substitution principle(LSP). 抽象定义是下面这样的 如果对每一个类型为T1的对象O1,都有类型为T2的对象O2,使得以T1定义 ...

  • 六大设计原则(二)LSP里氏替换原则

    里氏替换原则LSP(Liskov Subsituation Principle) 里氏替换原则定义 所有父类出现的地方可以使用子类替换并不会出现错误或异常,但是反之子类出现的地方不一定能用父类替换. ...

  • 软件设计的“七宗罪”及设计模式的七大原则

    编写软件过程中,面临着来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战,设计模式是为了让程序,具有更好的代码重用性.可读性.可扩展性.可靠性,使程序呈现高内聚低耦合的特性. 软件 ...

  • 设计模式的七大原则(6) --迪米特法则

    前言 迪米特法则,听名字有点奇怪,但是这个法则真的非常非常有意思,在我看来,这个法则其实描述的就是一个矜持的小姑娘,害羞的惹人怜爱.但是啊,姑娘虽好,切不可"贪杯"哦~ 基本介绍 ...

  • 设计模式的七大原则(5) --开闭原则

    前言 我们已经学习了单一职责原则,依赖倒置原则,接口隔离原则,李氏替换原则.可以说前面几个原则都是为了开闭原则奠定基础. 我们写的程序由于实际的情况可以一定程度上违背各种设计原则.但是,开闭原则我认为 ...

  • 设计模式的七大原则(3) --依赖倒置原则

    前言 上一节我们说了接口隔离原则,就是让接口的职责最小化.这样对维护代码简单,调用方法也清晰. 这节我们来研究依赖倒置原则.这个原则我认为是特别特别重要的.在很多地方我们能看到.比如Dubbo中使用到 ...

  • 设计模式的七大原则(1) --单一职责原则

    前言 最近工作中备受打击,之前设计的很多程序都被老大否决,需要重构,让我好好看看设计模式.之前对这一块内容的确不怎么重视,感觉枯燥无聊又派不上用场.后来沉下心来研究了一番... 我靠,原来如此,之前写 ...

  • 张际才:构图的七大原则,不要违背原则去创作

    张际才:构图的七大原则,不要违背原则去创作