龙空技术网

如何不改老代码也能实现新功能?

川后静波kimble 63

前言:

目前你们对“抽象类可以有方法的实现吗”都比较注重,各位老铁们都需要分析一些“抽象类可以有方法的实现吗”的相关资讯。那么小编同时在网络上汇集了一些有关“抽象类可以有方法的实现吗””的相关知识,希望兄弟们能喜欢,你们一起来学习一下吧!

00、背景

作为一名程序员,来了一个新需求就要改一次老代码,这种方式我们已经见怪不怪了,修改也很容易,只要我们按照之前的惯例如法炮制就好了。

这是一种不费脑子的做法,但是,经过长期积累,再来一个大一点的需求,改动量就要很大了。

而在这个过程中,每个人都很无辜,因为每个人都只是遵照惯例在修改。

但结果是,所有人都受到了伤害,代码越来越难以维护。

既然"修改"会带来这么多问题,那我们可以不修改吗?

开放封闭原则就提供了这样的一个新方向。

01、开放封闭原则

开闭原则,英文缩写OCP,全称 Open Closed Principle

开闭原则是 Bertrand Meyer 在其著作《面向对象软件构造》(Object-Oriented Software Construction)中提出来的,它给软件设计提出了一个极高的要求:不修改代码

《面向对象软件构造》

原文定义:

Software entities (classes, modules, functions) should be open for extension but closed for modification。

翻译如下:

软件实体(包括类、模块、功能等)应该对扩展开放,但是对修改关闭。

那如何不修改老代码,那又怎么实现新的需求呢?

答案就是靠扩展,也就是说新需求应该用新代码实现

02、原理解释对扩展开放

模块对扩展开放,就意味着需求变化时,可以对模块扩展,使其具有满足那些改变的新行为。

换句话说,模块通过扩展的方式去应对需求的变化。

对修改关闭

模块对修改关闭,表示当需求变化时,关闭对模块源代码的修改。

当然这里的“关闭”应该是尽可能不修改的意思,也就是说,应该尽量在不修改源代码的基础上面扩展组件。

03、为什么要“开”和“闭”

一般情况,我们接到需求变更的通知,通常方式可能就是修改模块的源代码。

然而修改已经存在的源代码是存在很大风险的,尤其是项目上线运行一段时间后,开发人员发生变化,这种风险可能就更大,常常有种边开车边换轮胎的感觉。

所以,为了避免这种风险,在面对需求变更时,我们一般不修改源代码,即所谓的对修改关闭

不允许修改源代码,我们如何应对需求变更呢?

答案就是我们下面要说的对扩展开放

通过扩展去应对需求变化,就要求我们必须要面向接口编程,或者说面向抽象编程

所有参数类型、引用传递的对象必须使用抽象(接口或者抽象类)的方式定义,不能使用实现类的方式定义。

通过抽象去界定扩展,比如我们定义了一个接口A的参数,那么我们的扩展只能是接口A的实现类。

04、举个小例子

有一个经验可以快速检验代码是否遵守了该原则:

如果我必须打开你某个模块的js文件并进行修改具体代码才能增强该模块的功能,则你写的这个模块无法通过“开放封闭原则”的检验

开放封闭原则向我们描述的是一个结果,就是我们可以不修改代码而仅凭扩展就完成新功能。

但是,这个结果的前提是要在软件内部留好扩展点,而这正是需要我们去设计的地方。

因为每一个扩展点都是一个需要设计的模型。

//iceCreamMaker.jslet iceCreamFlavors = ['巧克力', '香草'];//口味let iceCreamMaker = {  makeIceCream(flavor) {    if (iceCreamFlavors.indexOf(flavor) > -1) {      console.log('您选的口味有货,马上给您做冰激凌。');    } else {      console.log('哎呀,您选的口味我们没有。');    }  },};export default iceCreamMaker;

仔细看上面这段代码,若不编辑iceCreamFlavor数组就无法添加冰淇淋口味!

那我们应该如何来改进?

//iceCreamMaker.jslet iceCreamFlavors = ['巧克力', '香草'];//口味let iceCreamMaker = {  makeIceCream(flavor) {    if (iceCreamFlavors.indexOf(flavor) > -1) {      console.log('您选的口味有货,马上给您做冰激凌。');    } else {      console.log('哎呀,您选的口味我们没有。');    }  },  //增加口味  addFlavor(flavor) {    iceCreamFlavors.push(flavor);  },};export default iceCreamMaker;

现在,我们可以在代码中的任何位置调用addFlavor函数,以便添加其他美味的冰淇淋口味,而无需打开编辑iceCreamMaker.js文件。

这样便达到了只做增强,不做改变

总之,开放封闭原则可提高软件的可维护性与代码的重用性。

05、小结

在《Unix 编程艺术》一书中,Unix编程就提倡”提供机制,而不是策略“,这其实就是开放封闭原则的一种体现。

IntelliJ IDEA 和 Visual Studio Code,它们也都体现着开放封闭原则。

去了解它们的接口,可以看到这些优秀软件给我们提供的各种能力,这也是一种很好的学习方式。

开放封闭原则可以帮助我们改进自己的系统,我们可以通过查看自己的源码控制系统,找出那些最经常变动的文件,它们通常都是没有满足开放封闭原则的,而这可以成为我们改进系统的起点。

软件系统是变与不变的交融艺术,变化带来发展,不变的是本质,是共性。

没有不变的变化只是绚丽的海市蜃楼,透过变化抓住不变,才是抓住了核心与要义。

标签: #抽象类可以有方法的实现吗