『面试的底气』—— 设计模式之里氏代换原则|8月更文挑战

这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战

前言

在面试高级前端时,往往会遇到一些关于设计模式的问题,每次都回答不太理想。恰逢8月更文挑战的活动,准备用一个月时间好好理一下关于设计模式方面的知识点,给自己增加点面试的底气。

在学习设计模式之前,首先要认识到设计模式是个编程思想,对任何编程语言都适用。其次要从设计模式的原则开始学习,故本文将详细介绍设计模式的原则之一里氏代换原则

官方定义

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

自己的理解

官方的定义让人摸不着头脑,用白话文描述:在程序中,把父类都替换成它的子类,程序还是能正常运行。

里氏代换原则是开放-封闭原则的前提,为什么这么说呢?在开放-封闭原则中,父类保持封闭,用子类继续父类的方式,对父类进行扩展,实现开放。父类保持封闭,此时父类是可以被复用的。然而在实际开发过程中,在继承父类创建一个子类过程,经常会犯一毛病,在子类中去修改父类的方法和属性,这就导致父类不在封闭,如果父类被复用了,很有可能出现意想不到的BUG。

举个例子来说明:

class A {
    constructor() {
    }
    storageData() {
        api.getTaskList1()
            .then(res =>{
                localStorage.setItem(taskData", JSON.stringify(res.data) );
            })
    }
}
class B extends A {
    constructor() {
        super();
    }
    storageData() {
        api.getTaskList2()
            .then(res =>{
                localStorage.setItem("taskData", JSON.stringify(res.data));
            })
    }
}	
复制代码

上述代码中,子类B继承父类A,假设在程序中执行const a = new A();a.storageData();请求getTaskList1接口将其获取的数据缓存到浏览器的Local Storage的taskData中。

然而在某个地方,不经意执行了const a = new B();a.storageData();,此时变成请求getTaskList1接口将其获取的数据缓存到浏览器的Local Storage的taskData中,把浏览器的Local Storage中taskData的值给替换了,导致在程序中使用浏览器的Local Storage中的taskData数据的地方出错了。

如果在开发过程中,遵循里氏代换原则,这种情况根本不会发生。按照里氏代换原则,把const a = new A();替换成const a = new B();后程序是可以正常运行的。上面子类B继承父类A时,在子类B把父类A中的storageData方法给修改了,导致程序无法正常运行。

所以,里氏代换原则有一个更通俗的定义:子类可以扩展父类的功能,但不能改变父类原有的功能

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享