设计模式六大原则之里氏代换原则

目录

 

1、什么是里氏代换原则(Liskov Substitution Principle)?

2、为什么使用LSP?

3、如何正确使用LSP?


1、什么是里氏代换原则(Liskov Substitution Principle)?

总链接:https://blog.csdn.net/jjs15259655776/article/details/105619335

LSP最正宗的定义是:如果每一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都替换成o2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。

即:子类必须完全实现父类的方法。

里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范

2、为什么使用LSP?

面对对象里面的父类和子类,并不完全等于现实社会的包含关系。就是说对象1在现实社会中是属于对象2的,但是根据LSP,对象1不能是对象2的子类,否则就是违反了LSP,也是违反了开闭原则。违反了会怎么样?其实也不会怎么样,但是设计模式是人们进过很多项目实战,最终提炼出来的指导性的内容,对于项目的壮硕性和可维护性等方面是非常有益的。

第一个例子:正方形不是长方形。

从数学上的分类,正方形肯定属于长方形,但是,从面向对象的角度看,正方形设计为长方形的子类并不是一个好的设计。

长方形类:

public class Rectangle {
    private double length;
    private double width;


    public double getLength() {
        return length;
    }

    public void setLength(double length) {
        this.length = length;
    }

    public double getWidth() {
        return width;
    }

    public void setWidth(double width) {
        this.width = width;
    }

}

正方形类:由于正方形的长和宽相等,所以setLength和setWidth要保证length==width;

public class Square extends Rectangle {

    public void setLength(double length) {
        super.setLength(length);
        super.setWidth(length);
    }

    public void setWidth(double width) {
        super.setWidth(width);
        super.setLength(width);
    }
}

那么问题就来了:

假如我们把一个普通长方形作为参数传入resize方法,就会看到长方形宽度逐渐增长的效果,当宽度大于长度,代码就会停止,这种行为的结果符合我们的预期;假如我们再把一个正方形作为参数传入resize方法后,就会看到正方形的宽度和长度都在不断增长,代码会一直运行下去,直至系统产生溢出错误。所以,普通的长方形是适合这段代码的,正方形不适合。

class TestRectangle {
    public void resize(Rectangle objRect) {
        while(objRect.getWidth() <= objRect.getLength()) {
        objRect.setWidth(  objRect.getWidth () + 1 );
        }
    }
}

3、如何正确使用LSP?

可以看到如果我们的软件要完全符合LSP,需要投入一定量的分析。
在大中型的项目中,是一定要讲究软件工程的思想,讲究规范和流程的,否则人员协作和后期维护将会是非常困难的。
对于小型的项目可能相应的要简化很多,可能取决于时间、资源、商业等各种因素,但是多从软件工程的角度去思考问题,对于系统的健壮性、可维护性等性能指标的提高是非常有益的。
大家可以根据自己的需要(当然也不要偷懒),尽量的满足LSP。其实,这也是一种考虑、涉及上面的好习惯。

你可能感兴趣的:(设计模式,java编程)