博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《JavaScript设计模式与开发实践》原则篇(3)—— 开放-封闭原则
阅读量:6199 次
发布时间:2019-06-21

本文共 2875 字,大约阅读时间需要 9 分钟。

在面向对象的程序设计中,开放封闭原则(OCP)是最重要的一条原则。很多时候,一个程序具有良好的设计,往往说明它是符合开放封闭原则的。 当需要改变一个程序的功能或者给这个程序增加新功能的时候,可以使用增加代码的方式,但是不允许改动程序的源代码。

故事背景

假设我们是一个大型 Web 项目的维护人员,在接手这个项目时,发现它已经拥有10万行以上的JavaScript代码和数百个 JS 文件。 不久后接到了一个新的需求,即在 window.onload 函数中打印出页面中的所有节点数量。这 当然难不倒我们了。于是我们打开文本编辑器,搜索window.onload函数在文件中的位置,在函数内部添加以下代码

window.onload = function(){     // 原有代码略    console.log( document.getElementsByTagName( '*' ).length ); };复制代码

应用OCP原则

Function.prototype.after = function( afterfn ){     var __self = this;    return function(){        var ret = __self.apply( this, arguments );         afterfn.apply( this, arguments );        return ret;    } };window.onload = ( window.onload || function(){} ).after(function(){     console.log( document.getElementsByTagName( '*' ).length );});复制代码

通过动态装饰函数的方式,我们完全不用理会从前 window.onload 函数的内部实现,就算拿到的是一份混淆压缩过的代码也没有关系。只要它从前是个稳定运行的函数,那么以后也不会因为我们的新增需求而产生错误。新增的代码和原有的代码可以互不影响。

编写符合OCP代码的方法

过多的条件分支语句是造成程序违反开放封闭原则的一个常见原因。每当需要增加一个新 的 if 语句时,都要被迫改动原函数。实际上,每当我们看到一大片的 if 或者 swtich-case 语句时,第一时间就应该考虑,能否利用对象的多态性来重构它们。

利用多态的思想

利用对象的多态性来让程序遵守开放封闭原则,是一个常用的技巧。

  • 不符合OCP
var makeSound = function( animal ){    if ( animal instanceof Duck ){         console.log( '嘎嘎嘎' );     } else if ( animal instanceof Chicken ) {        console.log( '咯咯咯' );    }};var Duck = function(){}; var Chicken = function(){};makeSound( new Duck() ); makeSound( new Chicken() );//动物世界里增加一只狗之后,makeSound 函数必须改成:var makeSound = function( animal ){     if ( animal instanceof Duck ){        console.log( '嘎嘎嘎' );     } else if ( animal instanceof Chicken ) {        console.log( '咯咯咯' );     } else if ( animal instanceof Dog ) {        console.log('汪汪汪' );     }};var Dog = function(){};// 增加跟狗叫声相关的代码 makeSound( new Dog() ); // 增加一只狗复制代码

利用多态的思想,我们把程序中不变的部分隔离出来(动物都会叫),然后把可变的部分封 装起来(不同类型的动物发出不同的叫声),这样一来程序就具有了可扩展性。当我们想让一只狗发出叫声时,只需增加一段代码即可,而不用去改动原有的 makeSound函数

var makeSound = function( animal ){     animal.sound();};var Duck = function(){};Duck.prototype.sound = function(){     console.log( '嘎嘎嘎' );};var Chicken = function(){};Chicken.prototype.sound = function(){     console.log( '咯咯咯' );};makeSound( new Duck() ); // 嘎嘎嘎makeSound( new Chicken() ); // 咯咯咯/********* 增加动物狗,不用改动原有的 makeSound 函数 ****************/var Dog = function(){}; Dog.prototype.sound = function(){console.log( '汪汪汪' ); };makeSound( new Dog() ); // 汪汪汪复制代码
放置挂钩

放置挂钩(hook)也是分离变化的一种方式。我们在程序有可能发生变化的地方放置一个挂钩,挂钩的返回结果决定了程序的下一步走向。这样一来,原本的代码执行路径上就出现了一个 分叉路口,程序未来的执行方向被预埋下多种可能性。

使用回调函数

在 JavaScript 中,函数可以作为参数传递给另外一个函数,这是高阶函数的意义之一。在这 种情况下,我们通常会把这个函数称为回调函数。在 JavaScript版本的设计模式中,策略模式和命令模式等都可以用回调函数轻松实现。 回调函数是一种特殊的挂钩。我们可以把一部分易于变化的逻辑封装在回调函数里,然后把 回调函数当作参数传入一个稳定和封闭的函数中。当回调函数被执行的时候,程序就可以因为回 调函数的内部逻辑不同,而产生不同的结果。

总结

开放封闭原则是一个看起来比较虚幻的原则,但我们还是能找到一些让程序尽量遵守开放封闭原则的规律,最明显的就是找出程序中将要发生变化的地方,然后把变化封装起来。 通过封装变化的方式,可以把系统中稳定不变的部分和容易变化的部分隔离开来。在系统的 演变过程中,我们只需要替换那些容易变化的部分,如果这些部分是已经被封装好的,那么替换起来也相对容易。而变化部分之外的就是稳定的部分。在系统的演变过程中,稳定的部分是不需要改变的。

系列文章:

转载地址:http://qfnca.baihongyu.com/

你可能感兴趣的文章
python机器学习实战(三)
查看>>
正则表达式及简单bash编程
查看>>
关于购买Redis服务器:腾讯云、阿里云还是华为云?
查看>>
fopen/fclose
查看>>
win7x64 连接oracle 客户端 vs 2010调试 提示“ORA-12154: TNS: 无法解析指定的连接标识符 ”ORA-06413 问题(转)...
查看>>
查看entry和测试wallet
查看>>
oracle中substr函数的用法
查看>>
asm数据文件迁移(asm–>os)
查看>>
【转载】Python学习笔记——条件判断
查看>>
我的友情链接
查看>>
nginx 反向代理
查看>>
FZU 2159 WuYou
查看>>
我的友情链接
查看>>
运维自动化之ansible playbook安装node环境
查看>>
[原]列表的二级展开功能。在原生UITableView上扩展实现。
查看>>
centeros 安装 java resin
查看>>
Linux下安装JDK和TOMCAT,并简单配置虚拟主机
查看>>
Semi-sync master failed on net_flush() before wait
查看>>
抽奖算法
查看>>
CentOS系统启动流程-2015090401
查看>>