• 面向对象设计原则之三:里氏替换原则


    里氏替换原则(Liskov Substitution Principle LSP

     

          里氏替换原则是面向对象设计的基本原则之一。任何基类可以出现的地方,子类一定可以出现。LSP是继承复用的基石,只有当子类可以替换基类,软件单位的功能不受影响时,基类才能真正的被复用,而子类也可以在基类的基础上增加新的行为。

          Liskov提出了关于继承的原则:Inheritance should ensure that any property proved about supertype objects also holds for subtype objects.----继承必须确保超类中所拥有的性质在子类中仍然成立。2002年,软件工程大师Robert C. Martin出版了一本《Agile Software DevelopmentPrinciples Patterns and Practices》,在文中他把里氏代换原则最终简化为一句话:“Subtypes must be substitutable for their base types”也就是说子类必须能够替换成他们的基类。

          里氏替换原则讲的是基类和子类的关系,只有这种关系存在的时候里氏替换原则才能成立。里氏替换原则是实现开放封闭原则的具体规范。这是因为:实现开放封闭原则的关键是抽象,而继承关系又是抽象的一种具体实现。

    我们大家都打过CS的游戏,用枪射击杀人,如下类图:

                                       

          枪的主要职责是射击,如何射击在各个具体的子类中定义。注意在类中调用其他类时务必调用父类或接口,如果不能掉话父类或接口,说明类的射击已经违反了LSP原则。

    如果我们有一个玩具手 枪,该如何定义呢?我们先在类图2-1上增加一个类ToyGun,然后继承于AbstractGun类,修改后的类图如下:

                                           

                              

          玩具枪是不能用来射击的,杀不死人的,这个不应该写shoot方法,在这种情况下业务的调用类就会出现问题。为了解决这个问题,ToyGun可以脱离继承,建立一个独立的父类,为了做到代码可以服用,可以与AbstractGun建立关联委托关系,如下图:

                                  

    因此,如果子类不能完整地实现父类的方法,那么建议断开父子继承关系,采用依赖,聚合,组合等关系代替继承。

    子类可以有自己的属性或方法。

    覆盖或实现父类的方法时输入的参数可以放大。

    覆盖或实现父类的方法时输出结果可以被缩小。这是什么意思呢,父类的方法返回值是一个类型T,子类相同的方法(覆写)的返回值为类型S,那么根据里氏替换原则就要求S必须小于等于T,也就是说要么S和T是同一个类型,要么S是T的子类型。

         采用里氏替换原则的目的就是增加程序的健壮性,需求变更时也可以保持良好的兼容性和稳定性,即使增加子类,原有的子类可以继续运行。在实际项目中,每个子类对应不同的业务含义,使用父类作为参数,传递不同的子类完成不同业务逻辑。

  • 相关阅读:
    手动编译安装nginx
    centoos 安装hadoop集群
    block中如何避免循环引用
    正则表达式
    iOS开发ARC内存管理
    block的内部实现
    Block存储区域
    block的语法
    Collection(数组、字典、集合)
    block捕获自动变量和对象
  • 原文地址:https://www.cnblogs.com/mamxfx/p/7148064.html
Copyright © 2020-2023  润新知