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

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

前言

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

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

官方定义

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

本身的理解

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

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

举个例子来讲明:浏览器

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数据的地方出错了。markdown

若是在开发过程当中,遵循里氏代换原则,这种状况根本不会发生。按照里氏代换原则,把const a = new A();替换成const a = new B();后程序是能够正常运行的。上面子类B继承父类A时,在子类B把父类A中的storageData方法给修改了,致使程序没法正常运行。编程语言

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

相关文章
相关标签/搜索