zoukankan      html  css  js  c++  java
  • 设计模式七大原则-里氏替换原则

    基本介绍:

    里氏替换原则在1988年,由麻省理工学院的一位姓里的女士提出的

    她提出了这么一个思想:如果对每个类型为T1的对象o1,都有类型为T2的对象o2,是的以T1定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。换句话说,所有应用基类的地方必须能透明地使用其子类的对象

    在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法

    里氏替换原则告诉我们,继承实际上让两个类耦合性增强了,在适当的情况下,可以通过聚合,组合,依赖来解决问题。

    应用案例:

    说明:

    A类中有一个func1的方法求两数之差

    B类继承A类,但是要新增一个功能,求两数之和再和9相加

     1 package cn.rabcheng.liskovsubstitution;
     2 
     3 /**
     4  * @auther cheng
     5  * @create 2020-08-15 10:58
     6  * 里氏替换原则
     7  */
     8 public class LiskovSubstitution {
     9 
    10     public static void main(String[] args) {
    11 
    12         A a = new A();
    13         System.out.println("11 - 3 = " + a.func1(11,3));
    14         System.out.println("1 - 8 = " + a.func1(1,8));
    15 
    16         System.out.println("=====================");
    17 
    18         B b = new B();
    19         System.out.println("11 - 3 = " + b.func1(11,3));//本意是调用父类的方法求出11-3
    20         System.out.println("1 - 8 = " + b.func1(1,8));//本意是调用父类的方法求出1-8
    21         System.out.println("11 + 3 + 9 = "+ b.func2(11,3));
    22 
    23     }
    24 }
    25 
    26 class A{
    27     //返回两个数的差
    28     public int func1(int num1,int num2){
    29         return num1 - num2;
    30     }
    31 }
    32 
    33 //B类的本意是新增一个功能:
    34 //增加一个两数相加的功能,然后再和9求和
    35 //无意间第一个方法名写的和A类的方法名一样了,参数也一样相当于重写了A类额方法
    36 class B extends A{
    37 
    38     public int func1(int num1,int num2){
    39         return num1 + num2;
    40     }
    41 
    42     public int func2(int a,int b){
    43         return func1(a,b) + 9;
    44     }
    45 
    46 }
    47 11 - 3 = 8
    48 1 - 8 = -7
    49 =====================
    50 11 - 3 = 14
    51 1 - 8 = 9
    52 11 + 3 + 9 = 23

    结果和预期的结果不满足,程序发生了改变。

    发现原来运行正常的程序相减功能发生了错误,原因就是B类中无意重写了父类A中的func1方法,造成原油功能出现错误,在实际编程中,我们常常会通过重写父类的方法完成新的功能,这样写起来虽然简单,但是整个继承体系的复用性会比较差,特别是运行多台比较频繁的时候

    通用的做法是:原来的父类和子类都继承一个更通俗的基类,原有的继承关系去掉,采用依赖、聚合、组合灯关系替代。

    解决方法:

    创建一个更加基础的基类,把更加基础的方法和成员写到Base类

    让类A和类B分别继承Base类

    使用组合的方式调用A中的方法

     1 package cn.rabcheng.liskovsubstitution;
     2 
     3 /**
     4  * @auther cheng
     5  * @create 2020-08-15 11:19
     6  */
     7 public class LiskovSubstitution2 {
     8 
     9     public static void main(String[] args) {
    10         A2 a = new A2();
    11         System.out.println("11 - 3 = " + a.func1(11,3));
    12         System.out.println("1 - 8 = " + a.func1(1,8));
    13 
    14         System.out.println("=====================");
    15 
    16         B2 b = new B2();
    17         System.out.println("11 + 3 = " + b.func1(11,3));//本意是调用父类的方法求出11-3
    18         System.out.println("1 + 8 = " + b.func1(1,8));//本意是调用父类的方法求出1-8
    19         System.out.println("11 + 3 + 9 = "+ b.func2(11,3));
    20 
    21         //使用组合调用A类方法
    22         System.out.println("11 - 3 = " + b.func3(11,3));
    23     }
    24 }
    25 
    26 //创建一个更加基础的基类
    27 class Base{
    28     //把更更加基础的方法和成员写到Base类中
    29 }
    30 
    31 class A2 extends Base{
    32     //返回两个数的差
    33     public int func1(int num1,int num2){
    34         return num1 - num2;
    35     }
    36 }
    37 
    38 class B2 extends Base{
    39     public int func1(int num1,int num2){
    40         return num1 + num2;
    41     }
    42 
    43     public int func2(int a,int b){
    44         return func1(a,b) + 9;
    45     }
    46 
    47     //如果B类需使用A类的方法,使用组合关系
    48     private A2 a = new A2();
    49 
    50     //使用A2中的方法
    51     public int func3(int a,int b){
    52         return this.a.func1(a,b);
    53     }
    54 }
    55 11 - 3 = 8
    56 1 - 8 = -7
    57 =====================
    58 11 + 3 = 14
    59 1 + 8 = 9
    60 11 + 3 + 9 = 23
    61 11 - 3 = 8

    继承包含这样一层含义,父类中凡是已经实现好的方法,实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些已经实现好的方法任意修改,就会对整个继承体系造成破坏。

    继承在给程序设计带来便利的同时,也带来了弊端,比如使用继承会给程序带来侵入性,程序的可移植性降低,增加对象间的耦合性,如果一个类被其他类所继承,泽当这个类需要修改时,必须考虑到所有的子类,并且谷类修改后,所有涉及到子类的功能都有可能产生故障

    所以,在编程中如果要使用继承,需要遵循里氏替换原则

  • 相关阅读:
    LeetCode-079-单词搜索
    awk学习笔记
    Python实现排列组合算法
    python模拟登录人人
    Python的SQLite数据库使用方法
    C语言排序算法——插入排序算法
    C语言排序算法——简单选择排序算法
    C语言排序算法——冒泡排序算法
    Python学习——python的函数参数传递
    Python学习——实现secure copy功能
  • 原文地址:https://www.cnblogs.com/Rabcheng/p/13508071.html
Copyright © 2011-2022 走看看