当前位置: 移动技术网 > IT编程>软件设计>设计模式 > 6大设计原则之里氏替换原则

6大设计原则之里氏替换原则

2018年12月25日  | 移动技术网IT编程  | 我要评论
面对对象中的继承 优点如下: 缺点如下: 里氏替换原则的定义 如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型S是类型T的子类型. 通俗点讲,只要父类能出现的地方子类就可以出现,而且替换成子类也不会产生 ...

面对对象中的继承

优点如下:

  1. 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性
  2. 提高代码的重用性
  3. 子类可以形如父类,但又异于父类
  4. 提高代码的可扩展性,很多开源框架的扩展接口都是通过继承父类来实现的
  5. 提高产品或项目的开放性

缺点如下:

  1. 继承是侵入性的.只要继承,就必须拥有父类的所有属性和方法
  2. 降低代码的灵活性.子类必须拥有父类的属性和方法,让子类自由的世界中多了些约束
  3. 增强了耦合性.当父类的常量、变量和方法被修改时,需要考虑子类的修改,有时更会带来非常糟糕的结果--大段代码需要重构

里氏替换原则的定义

如果对每一个类型为s的对象o1,都有类型为t的对象o2,使得以t定义的所有程序p在所有的对象o1都代换成o2时,程序p的行为没有发生变化,那么类型s是类型t的子类型.

通俗点讲,只要父类能出现的地方子类就可以出现,而且替换成子类也不会产生任何错误或异常,使用者可能根本不需要知道是父类还是子类.但是反过来就不行了,有子类出现的地方,父类未必能适应.

里氏替换原则的规范(继承的规范)

1.子类必须完全实现父类的方法

例如有一个打枪的游戏,类图如下

6大设计原则之里氏替换原则

 

其 soldier 代码如下

6大设计原则之里氏替换原则

 

注意: 在类中调用其他类时,要使用父类或接口,否则就违背了里氏替换原则

这时,如果有一个玩具枪 toygun, 继承自 abstractgun,显然是不合适的,因为玩具枪没有伤害,可以新建一个抽象类 abstracttoy,将声音、形状都委托给 abstractgun 处理,然后两个基类下的子类自由延展,互不影响

注意: 如果子类不能完整的实现弗雷的方法,或者弗雷的某些方法在子类中已经发生"畸变",则建议断开父子继承关系,采用依赖、聚集、组合等关系替代

2.子类可以有自己的个性

里氏替换原则可以正着用,但不能反着用.在子类出现的地方,父类未必就可以胜任

3.覆盖或实现父类的方法是输入参数可以被放大

举个例子,先定义一个 father 类

6大设计原则之里氏替换原则

 

然后再定义一个子类:

6大设计原则之里氏替换原则

 

虽然子类方法与父类方法同名,但不是覆写父类方法,而是重载,因为输入参数不同

父类的参数范围小,当调用子类 dosomething方法时,若参数为hashmap调用父类方法,若为map调用子类方法

要是反过来,子类的 参数比父类范围下,就违背了里氏替换原则

4.覆写或实现父类的方法是输出结果可以被缩小

这个也不难理解,也就是说父类方法返回的是map时,子类可以返回hashmap

但是反过来,父类返回的是hashmap,而子类返回map类型就违背了里氏替换原则

采用里氏替换原则的好处

增强程序的健壮性,版本升级是也可以保持非常好的兼容性.即使增加子类,原有的子类还可以继续运行.在实际项目中,每个子类对应不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑,完美!


采用里氏替换原则,应尽量避免子类的"个性",一旦子类有"个性",这个子类和父类之间的关系就很难调和了,把子类当作父类使用,将子类的"个性"抹杀;把子类单独作为一个业务来使用,会让代码间的耦合关系变得扑朔迷离


 

 

可以关注一下鄙人的公众号, 谢谢各位了!

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网