全国免费咨询:

13245491521

VR图标白色 VR图标黑色
X

中高端软件定制开发服务商

与我们取得联系

13245491521     13245491521

2024-09-03_基于装饰器——我劝你不要在业务代码上装逼!!!

您的位置:首页 >> 新闻 >> 行业资讯

基于装饰器——我劝你不要在业务代码上装逼!!! 点击关注公众号,“技术干货”及时达!装饰器模式的定义在传统的面向对象语言中,给对象添加功能常使用继承的方式,但继承的方式并不灵活,会带来一些许多问题,如:超类和子类存在强耦合性,也就是说当改变超类时,子类也需要改变。而装饰器模式的出现改变的这种方式,装饰器模式可在不改变现有对象解构的基础上,动态地为对象添加功能。传统的 JavaScript 装饰器varplane={ fire:function(){ console.log("普通子弹"); }, }; varmissleDecorator=function(){ console.log("发射导弹"); }; varatomDecorator=function(){ console.log("发射原子弹"); }; varfire1=plane.fire; plane.fire=function(){ fire1(); missleDecorator(); }; varfire2=plane.fire; plane.fire=function(){ fire2(); atomDecorator(); }; plane.fire(); /** 普通子弹 发射导弹 发射原子弹 */ 装饰函数在 JavaScript 中,几乎一切都是对象,其中函数也被成为对象,在平时的开发中,我们都在和函数打交道。在给对象扩展属性和方法时,很难在不改动原功能函数的情况下,给函数添加一些额外的功能,最直接的粗暴方式就是直接改写函数,但这是最差的方式,这违反了开放——封闭原则。如下:functiona(){ console.log(1); } //改写: functiona(){ console.log(1); //新功能 console.log(2); } 很多时候,我们都不想去触碰之前的一些代码,但需要添加功能,所以如果需要在不改变原功能函数的情况下,给函数添加功能。可使用以下方式:要想完美的给函数添加功能,可使用 AOP 来装饰函数。AOP:一种编程规范,通过将关注点从主业务逻辑中剥离出来并单独处理,以此来提高代码的可读性和重用性。如下:Function.prototype.before=function(beforeFn){ var_self=this; returnfunction(){ beforeFn.apply(this,arguments); return_self.apply(this,arguments); }; Function.prototype.after=function(afterFn){ var_self=this; returnfunction(){ varret=_self.apply(this,arguments); afterFn.apply(this,arguments); return } } // before 和 after 函数都接收一个函数作为参数,这个函数也就是新添加的函数(里面也就是要添加的新功能逻辑)。 //而before 和 after 函数区别在于在是原函数之前执行还是之后执行。 AOP 函数的使用Function.prototype.before=function(beforeFn){ var_self=this; returnfunction(){ beforeFn.apply(this,arguments); return_self.apply(this,arguments); }; Function.prototype.after=function(afterFn){ var_self=this; returnfunction(){ varret=_self.apply(this,arguments); afterFn.apply(this,arguments); return } } varo1=function(){ console.log('1'); } varo2=function(){ console.log('2'); } varo3=function(){ console.log('3'); } vardesctor=o1.after(o2); desctor=desctor.after(o3); desctor();//123 /** vardesctor=o1.after(o2); desctor=desctor.after(o3); desctor(); 1 2 3 vardesctor=o1.before(o2); desctor=desctor.before(o3); desctor(); 3 2 1 vardesctor=o1.after(o2); desctor=desctor.before(o3); desctor(); 3 1 2 vardesctor=o1.before(o2); desctor=desctor.after(o3); desctor(); 2 1 3 */ AOP的应用1.数据上报在程序开发中,当业务代码开发完后,在结尾时需要加很多的日志上报的代码,普遍我们会去改已经之前封装好的功能函数。其实这并不是一个好的方式,那如何在不直接修改之前函数的基础上添加日志上报功能呢?如下:!DOCTYPEhtml htmllang="en" head metacharset="UTF-8"/ titleAOP日志上报/title metahttp-equiv="X-UA-Compatible"content="IE=edge"/ metaname="viewport"content="width=device-width,initial-scale=1.0"/ scriptsrc="https://unpkg.com/vue@3.2.20/dist/vue.global.js"/script /head body divid="app" buttonclass="btn"@click="handler"Button/button pid="tt"{{message}}/p /div /body /html scripttype="text/javascript" //logreport const{reactive,ref,createApp}= constapp=createApp({ setup(){ constmessage=ref("未点击"); constcount=ref(0); Function.prototype.before=function(beforeFn){ var_self=this; returnfunction(){ beforeFn.apply(this,arguments); return_self.apply(this,arguments); Function.prototype.after=function(afterFn){ var_self=this; returnfunction(){ varret=_self.apply(this,arguments); afterFn.apply(this,arguments); return functionhandler(){ message.value=`已点击${++count.value}`; } handler=handler.after(log); functionlog(){ message.value=message.value+"-----logreported"; console.log("logreport"); } return{ message, handler, }, app.mount("#app"); /script 2.动态参数在日常开发中,我们需要向后台接口发送请求来获取信息,例如传参如下。业务在后续时需要添加新参数,每个接口需要把 token 值也一并传过去, 普遍我们会去改封装的请求方法,把 token 参数添加进去。但我们直接修改封装好的请求方法不是好的行为,那我们可使用上面说过的 AOP 方式来改进。{ name:'xxxx', password:'xxxx', } 如下:!DOCTYPEhtml htmllang="en" head metacharset="UTF-8"/ titleAOP动态参数/title metahttp-equiv="X-UA-Compatible"content="IE=edge"/ metaname="viewport"content="width=device-width,initial-scale=1.0"/ scriptsrc="https://unpkg.com/vue@3.2.20/dist/vue.global.js"/script /head body divid="app"{{message}}/div /body /html scripttype="text/javascript" const{reactive,ref,createApp}= constapp=createApp({ setup(){ constmessage=ref("emptyparams"); Function.prototype.before=function(beforeFn){ var_self=this; returnfunction(){ beforeFn.apply(this,arguments); return_self.apply(this,arguments); Function.prototype.after=function(afterFn){ var_self=this; returnfunction(){ varret=_self.apply(this,arguments); afterFn.apply(this,arguments); return functionajax(type,url,params){ message.value=`${type}----${url}-----${JSON.stringify(params)}`; } functiongetToken(){ //dosomething return'token'; } ajax=ajax.before(function(type,url,params){ params.token=getToken(); }) ajax('get','https://www.baidu.com/userinfo',{name:'se',password:'xsdsd'}); return{ message, }, app.mount("#app"); /script 3.表单校验在日常开发中,我们经常要去做校验表单数据,通常的方式是在功能函数中进行判断处理或将判断逻辑提取为一个函数的方式。但这种方式其实是与功能性函数相混合,且校验逻辑与功能性函数有耦合关系。那我们可使用 AOP 方式来改进。如下:!DOCTYPEhtml htmllang="en" head metacharset="UTF-8"/ titleAOP表单验证/title metahttp-equiv="X-UA-Compatible"content="IE=edge"/ metaname="viewport"content="width=device-width,initial-scale=1.0"/ scriptsrc="https://unpkg.com/vue@3.2.20/dist/vue.global.js"/script /head body divid="app" label 姓名: input type="text" v-model="data.name" placeholder="请输入姓名" / /label label 密码: input type="text" v-model="data.pass" placeholder="请输入密码" / /label pv-if="data.name||data.pass"{{data.name+'/'+data.pass}}----after-----{{data.message}}/p hr button@click="submitBtn"submit/button /div /body /html scripttype="text/javascript" const{reactive,ref,createApp,watchEffect}= constapp=createApp({ setup(){ constdata=reactive({ name:"", pass:"", message:"", Function.prototype.before=function(beforeFn){ var_self=this; returnfunction(){ if(beforeFn.apply(this,arguments)===false)return; return_self.apply(this,arguments); functionvalid(){ if(!data.name||!data.pass){ alert("用户名或密码不能为空"); returnfalse; } } functionformSubmit(){ console.log("data------",data); data.message=`${data.name}-------${data.pass}`; } formSubmit=formSubmit.before(valid); functionsubmitBtn(){ formSubmit(); } return{ data, submitBtn, }, app.mount("#app"); /script 装饰器模式的优缺点优点:扩展性强:装饰器模式允许在不修改现有代码的情况下,动态地添加新功能或修改现有功能。通过使用装饰器,可以在运行时按需组合和堆叠装饰器对象,实现各种组合方式,从而实现更多的功能扩展。遵循开闭原则:装饰器模式通过添加装饰器类来扩展功能,而不是修改现有的代码。这样可以保持原有代码的稳定性,符合开闭原则,即对扩展开放,对修改关闭。分离关注点:装饰器模式将功能的扩展和核心功能分离开来,每个装饰器类只关注单一的额外功能。这样可以使代码更加清晰、可读性更高,并且容易维护和测试。缺点:增加复杂性:使用装饰器模式会增加额外的类和对象,引入了更多的复杂性和层次结构。这可能使代码变得更加复杂,理解和调试起来可能更加困难。潜在的性能影响:由于装饰器模式涉及多个对象的组合和堆叠,可能会引入额外的运行时开销,对性能产生一定的影响。尤其是当装饰器链较长时,可能会导致性能下降。装饰器模式的适用场景动态地扩展对象功能:当需要在运行时动态地为对象添加额外的功能或责任时,装饰器模式是一个很好的选择遵循开闭原则:如果你希望在不修改现有代码的情况下扩展功能,而且要保持代码的稳定性,装饰器模式是一个合适的解决方案。分离关注点:当你希望将不同的功能分离开来,使每个功能都有自己独立的装饰器类时,装饰器模式是有用的。每个装饰器只关注单一的额外功能,这样可以使代码更加清晰、可读性更高,并且容易维护和测试。多层次的功能组合:如果你需要实现多个功能的组合,而且每个功能都可以灵活选择是否添加,装饰器模式可以很好地满足这个需求。通过堆叠多个装饰器对象,可以按照特定的顺序组合功能,实现各种组合方式。继承关系的替代方案:当你面临类似于创建大量子类的情况时,装饰器模式可以作为继承关系的替代方案。通过使用装饰器模式,可以避免创建过多的子类,而是通过组合不同的装饰器来实现不同的功能组合。Tip: 文章部分内容参考于曾探大佬的《JavaScript 设计模式与开发实践》。文章仅做个人学习总结和知识汇总点击关注公众号,“技术干货”及时达! 阅读原文

上一篇:2020-09-22_「转」倒计时5天,2020第三届中国青年动画导演论坛来了! 下一篇:2024-06-05_关于AI的颠覆性效应,三位企业家的预言

TAG标签:

18
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设网站改版域名注册主机空间手机网站建设网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。
项目经理在线

相关阅读 更多>>

猜您喜欢更多>>

我们已经准备好了,你呢?
2022我们与您携手共赢,为您的企业营销保驾护航!

不达标就退款

高性价比建站

免费网站代备案

1对1原创设计服务

7×24小时售后支持

 

全国免费咨询:

13245491521

业务咨询:13245491521 / 13245491521

节假值班:13245491521()

联系地址:

Copyright © 2019-2025      ICP备案:沪ICP备19027192号-6 法律顾问:律师XXX支持

在线
客服

技术在线服务时间:9:00-20:00

在网站开发,您对接的直接是技术员,而非客服传话!

电话
咨询

13245491521
7*24小时客服热线

13245491521
项目经理手机

微信
咨询

加微信获取报价