电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

聊Javascript中的AOP編程

瀏覽:4日期:2023-11-21 16:47:32
 Duck punch

我們先不談AOP編程,先從duck punch編程談起。

如果你去wikipedia中查找duck punch,你查閱到的應(yīng)該是monkey patch這個(gè)詞條。根據(jù)解釋,Monkey patch這個(gè)詞來源于 guerrilla patch,意為在運(yùn)行中悄悄的改變代碼,而 guerrilla 這個(gè)詞與 gorilla 同音,而后者意又與monkey相近(前者為“猩猩”的意思),最后就演變?yōu)榱薽onkey patch。

如果你沒有聽說過duck punch,但你或許聽說過duck typing。舉一個(gè)通俗的例子,如何辨別一只鴨子:

When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.

沒錯(cuò),如果我發(fā)現(xiàn)有一類動(dòng)物像鴨子一樣叫,像鴨子一樣游泳,那么它就是一只鴨子!

聊Javascript中的AOP編程

這個(gè)檢測(cè)看上去似乎有一些理所當(dāng)然和無厘頭,但卻非常的實(shí)用。 并且在編程中可以用來解決一類問題——對(duì)于Javascript或者類似的動(dòng)態(tài)語言,如何實(shí)現(xiàn)“接口”或者“基類”呢?我們可以完全不用在乎它們的過去如何,我們只關(guān)系在使用它們的時(shí)候,方法的類型或者參數(shù)是否是我們需要的:

var quack = someObject.quack;if (typeof quack == "function" && quck.length == arguLength){ // This thing can quack}

扯遠(yuǎn)了,其實(shí)我想表達(dá)的是duck punch其實(shí)是由duck typing演化而來的:

if it walks like a duck and talks like a duck, it’s a duck, right? So if this duck is not giving you the noise that you want, you’ve got to just punch that duck until it returns what you expect.

當(dāng)你想一只鴨子發(fā)出驢的叫聲怎么辦,揍到它發(fā)出驢的叫聲為止……話說這讓我想到一個(gè)非常形象的笑話:

為了測(cè)試美國(guó)、香港、中國(guó)大陸三地警察的實(shí)力, 聯(lián)合國(guó)將三只兔子放在三個(gè)森林中,看三地警察誰先找出兔子。任務(wù):找出兔子。 (中間省略……) 最后是某國(guó)警察,只有四個(gè),先打了一天麻將,黃昏時(shí)一人拿一警棍進(jìn)入森林,沒五分鐘,聽到森林里傳來一陣動(dòng)物的慘叫,某國(guó)警察一人抽著一根煙有說有笑的出來,后面拖著一只鼻青臉腫的熊,熊奄奄一息的說到:“不要再打了,我就是兔子……”

雖然duck punch有些暴力,但不失為一個(gè)有效的方法。落實(shí)到代碼上來說就是讓原有的代碼兼容我們需要的功能。比如Paul Irish博客上的這個(gè)例子:

/** 我們都知道jQuery的`$.css`方法可以通過使用顏色的名稱給元素進(jìn)行顏色賦值。 但jQuery內(nèi)置的顏色并非是那么豐富,如果我們想添加我們自定義的顏色名稱應(yīng)該怎么辦?比如我們想添加`Burnt Sienna`這個(gè)顏色*/(function($){// 把原方法暫存起來: var _oldcss = $.fn.css; // 重寫原方法: $.fn.css = function(prop,value){// 把自定義的顏色寫進(jìn)分支判斷里,特殊情況特殊處理if (/^background-?color$/i.test(prop) && value.toLowerCase() === 'burnt sienna') { return _oldcss.call(this,prop,'#EA7E5D');// 一般情況一般處理,調(diào)用原方法} else { return _oldcss.apply(this,arguments);} };})(jQuery);// 使用方法:jQuery(document.body).css('backgroundColor','burnt sienna')

同時(shí)可以推倒出duck punch的模式不過如此:

(function($){ var _old = $.fn.method; $.fn.method = function(arg1,arg2){if ( ... condition ... ) { return ....} else { // do the default return _old.apply(this,arguments);} };})(jQuery);

但是這么做有一個(gè)問題:需要修改原方法。這違背了“開放-封閉”原則,本應(yīng)對(duì)拓展開放,對(duì)修改關(guān)閉。怎么解決這個(gè)問題呢?使用AOP編程。

 AOP入門

AOP全稱為Aspect-oriented programming,很明顯這是相對(duì)于Object-oriented programming而言。Aspect可以翻譯為“切面”或者“側(cè)面”,所以AOP也就是面向切面編程。

怎么理解切面?

在面向?qū)ο缶幊讨校覀兌x的類通常是領(lǐng)域模型,它的擁有的方法通常是和純粹的業(yè)務(wù)邏輯相關(guān)。比如:

Class Person{ private int money; public void pay(int price) { this.money = this.money - price; }}

但通常實(shí)際情況會(huì)更復(fù)雜,比如我們需要在付款的pay方法中加入授權(quán)檢測(cè),或者用于統(tǒng)計(jì)的日志發(fā)送,甚至容錯(cuò)代碼。于是代碼會(huì)變成這樣:

Class Person{ private int money public void pay(price) {try { if (checkAuthorize() == true) {this.money = this.money - price; sendLog(); }}catch (Exception e){} }}

更可怕的是,其他的方法中也要添加相似的代碼,這樣以來代碼的可維護(hù)性和可讀性便成了很大的問題。我們希望把這些零散但是公共的非業(yè)務(wù)代碼收集起來,更友好的使用和管理他們,這便是切面編程。切面編程在避免修改遠(yuǎn)代碼的基礎(chǔ)上實(shí)現(xiàn)了代碼的復(fù)用。就好比把不同的對(duì)象橫向剖開,關(guān)注于內(nèi)部方法改造。而面向?qū)ο缶幊谈P(guān)注的是整體的架構(gòu)設(shè)計(jì)。

實(shí)現(xiàn)

在上一節(jié)中介紹的duck punch與切面編程類似,都是在改造原方法的同時(shí)保證原方法功能。但就像結(jié)尾說的一樣,直接修改原方法的模式有悖于面向?qū)ο笞罴褜?shí)踐的原則。

Javascript可以采用裝飾者模式(給原對(duì)象添加額外的職責(zé)但避免修改原對(duì)象)實(shí)現(xiàn)AOP編程。注意在這里強(qiáng)調(diào)的是實(shí)現(xiàn),我進(jìn)一步想強(qiáng)調(diào)的是,切面編程只是一種思想,而裝飾者模式只是實(shí)踐這種思想的一種手段而已,比如在Java中又可以采用代理模式等。切面編程在Java中發(fā)揮的余地更多,也更標(biāo)準(zhǔn),本想把Java的實(shí)現(xiàn)模式也搬來這篇文章中,但不才Java水平有限,對(duì)Java的實(shí)現(xiàn)不是非常理解。在這里就只展示Javascript的實(shí)現(xiàn)。

AOP中有一些概念需要介紹一下,雖然我們不一定要嚴(yán)格執(zhí)行

joint-point:原業(yè)務(wù)方法;advice:攔截方式point-cut:攔截方法

關(guān)于這三個(gè)概念我們可以串起來可以這么理解:

當(dāng)我們使用AOP改造一個(gè)原業(yè)務(wù)方法(joint-point)時(shí),比如加入日志發(fā)送功能(point-cut),我們要考慮在什么情況下(advice)發(fā)送日志,是在業(yè)務(wù)方法觸發(fā)之前還是之后;還是在拋出異常的時(shí)候,還是由日志發(fā)送是否成功再?zèng)Q定是否執(zhí)行業(yè)務(wù)方法。

比如gihub上的meld這個(gè)開源項(xiàng)目,就是一個(gè)很典型的AOP類庫(kù),我們看看它的API:

// 假設(shè)我們有一個(gè)對(duì)象myObject, 并且該對(duì)象有一個(gè)doSomething方法:var myObject = { doSomething: function(a, b) {return a + b; }};// 現(xiàn)在我們想拓展它,在執(zhí)行那個(gè)方法之后打印出剛剛執(zhí)行的結(jié)果:var remover = meld.after(myObject, 'doSomething', function(result) { console.log('myObject.doSomething returned: ' + result);});// 試試執(zhí)行看:myObject.doSomething(1, 2); // Logs: "myObject.doSomething returned: 3"http:// 這個(gè)時(shí)候我們想移除剛剛的修改:remover.remove();

由此可以看出,AOP接口通常需要三個(gè)參數(shù),被修改的對(duì)象,被修改對(duì)象的方法(joint-point),以及觸發(fā)的時(shí)機(jī)(adivce),還有觸發(fā)的動(dòng)作(point-cut)。上面說了那么多的概念,現(xiàn)在可能要讓各位失望了,Javascript的實(shí)現(xiàn)原理其實(shí)非常簡(jiǎn)單

function doAfter(target, method, afterFunc){ var func = target[method]; return function(){var res = func.apply(this, arguments);afterFunc.apply(this, arguments);return res; };}

當(dāng)然,如果想看到更完備的解決方案和代碼可以參考上面所說的meld項(xiàng)目

 結(jié)束語

這一篇一定讓你失望了,代碼簡(jiǎn)單又寥寥無幾。本篇主要在于介紹有關(guān)duck和AOP的這幾類思想,我想編程的樂趣不僅僅在于落實(shí)在編碼上,更在于整個(gè)架構(gòu)的設(shè)計(jì)。提高代碼的可維護(hù)性和可拓展性會(huì)比高深莫測(cè)的代碼更重要。

其實(shí)上面

 參考文獻(xiàn):How to Fulfill Your Own Feature Request -or- Duck Punching With jQuery!Duck Punching JavaScript - Metaprogramming with PrototypeDoes JavaScript have the interface type (such as Java’s ‘interface’)?AOP技術(shù)基礎(chǔ)
標(biāo)簽: JavaScript
相關(guān)文章:
主站蜘蛛池模板: 哈尔滨治「失眠/抑郁/焦虑症/精神心理」专科医院排行榜-京科脑康免费咨询 一对一诊疗 | 分光色差仪,测色仪,反透射灯箱,爱色丽分光光度仪,美能达色差仪维修_苏州欣美和仪器有限公司 | 喷涂流水线,涂装流水线,喷漆流水线-山东天意设备科技有限公司 | 筒瓦厂家-仿古瓦-寺庙-古建琉璃瓦-宜兴市古典园林建筑陶瓷厂有限公司 | 带式过滤机厂家_价格_型号规格参数-江西核威环保科技有限公司 | 压滤机-洗沙泥浆处理-压泥机-山东创新华一环境工程有限公司 | 铸铝门厂家,别墅大门庭院大门,别墅铸铝门铜门[十大品牌厂家]军强门业 | 杭州实验室尾气处理_实验台_实验室家具_杭州秋叶实验设备有限公司 | 刮板输送机,粉尘加湿搅拌机,螺旋输送机,布袋除尘器 | 荣事达手推洗地机_洗地机厂家_驾驶式扫地机_工业清洁设备 | 无锡网站建设_小程序制作_网站设计公司_无锡网络公司_网站制作 | 温州中研白癜风专科_温州治疗白癜风_温州治疗白癜风医院哪家好_温州哪里治疗白癜风 | 3d可视化建模_三维展示_产品3d互动数字营销_三维动画制作_3D虚拟商城 【商迪3D】三维展示服务商 广东健伦体育发展有限公司-体育工程配套及销售运动器材的体育用品服务商 | 滚珠丝杆升降机_螺旋升降机_丝杠升降机-德迈传动 | 齿轮减速机_齿轮减速电机-VEMT蜗轮蜗杆减速机马达生产厂家瓦玛特传动瑞环机电 | 扬州汇丰仪表有限公司| 岛津二手液相色谱仪,岛津10A液相,安捷伦二手液相,安捷伦1100液相-杭州森尼欧科学仪器有限公司 | GAST/BRIWATEC/CINCINNATI/KARL-KLEIN/ZIEHL-ABEGG风机|亚喜科技 | 洗砂机械-球磨制砂机-洗沙制砂机械设备_青州冠诚重工机械有限公司 | 郑州宣传片拍摄-TVC广告片拍摄-微电影短视频制作-河南优柿文化传媒有限公司 | 煤矿支护网片_矿用勾花菱形网_缝管式_管缝式锚杆-邯郸市永年区志涛工矿配件有限公司 | 液氮罐_液氮容器_自增压液氮罐-北京君方科仪科技发展有限公司 | 合肥宠物店装修_合肥宠物美容院装修_合肥宠物医院设计装修公司-安徽盛世和居装饰 | 智慧农业|农业物联网|现代农业物联网-托普云农物联网官方网站 | 整车VOC采样环境舱-甲醛VOC预处理舱-多舱法VOC检测环境仓-上海科绿特科技仪器有限公司 | 锤式粉碎机,医药粉碎机,锥式粉碎机-无锡市迪麦森机械制造有限公司 | 丹尼克尔拧紧枪_自动送钉机_智能电批_柔性振动盘_螺丝供料器品牌 | 耐酸碱胶管_耐腐蚀软管总成_化学品输送软管_漯河利通液压科技耐油耐磨喷砂软管|耐腐蚀化学软管 | 蔬菜配送公司|蔬菜配送中心|食材配送|饭堂配送|食堂配送-首宏公司 | 圆形振动筛_圆筛_旋振筛_三次元振动筛-河南新乡德诚生产厂家 | 地埋式垃圾站厂家【佳星环保】小区压缩垃圾中转站转运站 | led冷热冲击试验箱_LED高低温冲击试验箱_老化试验箱-爱佩百科 | 粉末冶金-粉末冶金齿轮-粉末冶金零件厂家-东莞市正朗精密金属零件有限公司 | 四探针电阻率测试仪-振实密度仪-粉末流动性测定仪-宁波瑞柯微智能 | 进口消泡剂-道康宁消泡剂-陶氏消泡剂-大洋消泡剂 | 不锈钢反应釜,不锈钢反应釜厂家-价格-威海鑫泰化工机械有限公司 不干胶标签-不干胶贴纸-不干胶标签定制-不干胶标签印刷厂-弗雷曼纸业(苏州)有限公司 | 回转炉,外热式回转窑,回转窑炉-淄博圣元窑炉工程有限公司 | 长沙网站建设制作「网站优化推广」-网页设计公司-速马科技官网 | ge超声波测厚仪-电动涂膜机-电动划格仪-上海洪富 | 北京开源多邦科技发展有限公司官网 | 快干水泥|桥梁伸缩缝止水胶|伸缩缝装置生产厂家-广东广航交通科技有限公司 |