摘要:實(shí)際上在這種將函數(shù)作為一等對(duì)象的語(yǔ)言里,策略模式已經(jīng)融入到了語(yǔ)言本身當(dāng)中,我們經(jīng)常使用高階函數(shù)來(lái)封裝不同的行為,并且把它傳遞到另一個(gè)函數(shù)中。
聲明:這個(gè)系列為閱讀《JavaScript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐》 ----曾探@著一書(shū)的讀書(shū)筆記
1.策略模式的定義將不變的部分和變化的部分隔開(kāi)是每個(gè)設(shè)計(jì)模式的主題。
2.策略模式的目的定義一系列的算法,把它們一個(gè)個(gè)封裝起來(lái),并且使它們可以相互替換。
將算法的使用與算法的實(shí)現(xiàn)分離開(kāi)來(lái)。
3.傳統(tǒng)語(yǔ)言中的策略模式和JavaScript中的策略模式對(duì)比 3.1.傳統(tǒng)語(yǔ)言中的策略模式使用策略模式來(lái)實(shí)現(xiàn)計(jì)算獎(jiǎng)金
var performances = function () {}; performances.prototype.calculate = function (salary) { return salary * 4; }; var performanceA =function () {}; performanceA.prototype.calculate=function (salary) { return salary * 3; }; var performanceB =function () {}; performanceB.prototype.calculate=function (salary) { return salary * 2; }; //定義獎(jiǎng)金類Bonus var Bonus =function () { this.salary = null; //原始工資 this.strategy = null;//績(jī)效等級(jí)對(duì)應(yīng)的策略對(duì)象 }; Bonus.prototype.setSalary=function (salary) { this.salary=salary; //設(shè)置員工的原始工資 }; Bonus.prototype.setStrategy=function (strategy) { this.strategy=strategy;//設(shè)置績(jī)效等級(jí)對(duì)應(yīng)的策略對(duì)象 }; Bonus.prototype.getBonus =function () { //取得獎(jiǎng)金數(shù)額 return this.strategy.calculate(this.salary);//把計(jì)算獎(jiǎng)金的操作委托給對(duì)應(yīng)的策略對(duì)象 }; var bonus = new Bonus(); bonus.setSalary(10000); bonus.setStrategy(new performances());//設(shè)置策略對(duì)象 console.log(bonus.getBonus()); bonus.setStrategy(new performanceA()); console.log(bonus.getBonus());
定義有系列的算法,把它們各自封裝成策略類,算法被封裝在策略類內(nèi)部的方法里。在客戶端對(duì)Context發(fā)起請(qǐng)求的時(shí)候,Context總是把請(qǐng)求委托給這些策略對(duì)象中間的某一個(gè)進(jìn)行計(jì)算。
3.2.JavaScript中的策略模式//封裝的策略算法 var strategies={ "S":function (salary) { return salary * 4; }, "A":function (salary) { return salary * 3; }, "B":function (salary) { return salary * 2; } }; //具體的計(jì)算方法 var calculateBonus=function (level, salary) { return strategies[level](salary); }; console.log(calculateBonus("S",1000)); console.log(calculateBonus("A",4000));
使用策略模式重構(gòu)代碼,可以消除程序中大片的條件分支語(yǔ)句。在實(shí)際開(kāi)發(fā)中,我們通常會(huì)把算法的含義擴(kuò)散開(kāi)來(lái),使策略模式也可以用來(lái)封裝一系列的“業(yè)務(wù)規(guī)則”。只要這些業(yè)務(wù)規(guī)則指向的目標(biāo)一致,并且可以被替換使用,我們就可以使用策略模式來(lái)封裝他們。
4.策略模式實(shí)現(xiàn)的表單校驗(yàn) 4.1使用JavaScript來(lái)實(shí)現(xiàn)的一個(gè)支持多重校驗(yàn)規(guī)則表單校驗(yàn)//策略對(duì)象 var strategies = { isNonEmpty: function (value, errorMsg){ if (value === "") { return errorMsg; } }, minLength: function (value, length, errorMg){ if (value.length < length) { return errorMg; } }, isMobile: function (value, errorMsg){ if (!/(^1[3|5|8][0-9]{9}$)/.test(value)) { return errorMsg; } } }; /** * Validator 類 * @constructor */ var Validator = function (){ this.cache = []; }; Validator.prototype.add = function (dom, rules){ var self = this; for (var i = 0, rule; rule = rules[i++];) { (function (rule){ var strategyAry=rule.strategy.split(":"); var errorMsg=rule.errorMsg; self.cache.push(function (){ var strategy=strategyAry.shift(); strategyAry.unshift(dom.value); strategyAry.push(errorMsg); return strategies[strategy].apply(dom,strategyAry); }) })(rule) } }; Validator.prototype.start=function (){ for (var i=0,validatorFunc;validatorFunc=this.cache[i++];){ var errorMsg=validatorFunc(); if(errorMsg){ return errorMsg; } } }; //客戶端調(diào)用的代碼 var registerForm=document.getElementById("registerForm"); var validataFunc=function (){ var validator=new Validator(); validator.add(registerForm.userName,[{ "strategy":"isNonEnpty", "errorMsg":"用戶名不能為空" },{ "strategy":"minLength", "errorMsg":"用戶名長(zhǎng)度不能小于10位" }]); // validator.add(registerForm.password,[]) var errorMsg =validator.start(); return errorMsg; }; registerForm.onsubmit=function (){ var errorMsg=validataFunc(); if(errorMsg){ alert(errorMsg); return false; } };4.2策略模式的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):
策略模式利用組合,委托和多態(tài)等技術(shù)思想,可以有效的避免多重條件選擇語(yǔ)句;
策略模式提供了對(duì)開(kāi)放-封閉原則的完美支持,將算法封裝在獨(dú)立的strategy中,使得它們易于切換,易于理解,易于擴(kuò)展。
策略模式中的算法也可以復(fù)用在系統(tǒng)的其它地方,從而避免許多重復(fù)的復(fù)制粘貼工作。
在策略模式中利用組合和委托來(lái)讓Context擁有執(zhí)行算法的能力,這也是繼承的一種更輕便的替代方案。
缺點(diǎn):
策略模式會(huì)在程序中添加許多的策略類和策略對(duì)象
要使用策略模式,就必須要了解各個(gè)strategy和他們之間的不同點(diǎn),這樣才能選擇一個(gè)合適的strategy。
4.3函數(shù)多態(tài)性的描述在函數(shù)作為一等對(duì)象的語(yǔ)言中,策略模式是隱形的。strategy就是值為函數(shù)的變量。
在JavaScript中,除了使用類來(lái)封裝算法和行為之外,使用函數(shù)當(dāng)然也是一種選擇。這些“算法”可以被封裝到函數(shù)中并且四處傳遞,也就是我們常說(shuō)的“高階函數(shù)”。
實(shí)際上在JavaScript這種將函數(shù)作為一等對(duì)象的語(yǔ)言里,策略模式已經(jīng)融入到了語(yǔ)言本身當(dāng)中,我們經(jīng)常使用高階函數(shù)來(lái)封裝不同的行為,并且把它傳遞到另一個(gè)函數(shù)中。當(dāng)我們對(duì)這些函數(shù)發(fā)出“調(diào)用”的消息時(shí),不同的函數(shù)會(huì)返回不同的執(zhí)行結(jié)果。所以在JavaScript中,“函數(shù)對(duì)象的多態(tài)性”會(huì)更加簡(jiǎn)單些。
總結(jié):在JavaScript語(yǔ)言的策略模式中,策略類往往被函數(shù)所代替,這時(shí)策略模式就成了一種“隱形”的模式。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/86430.html
摘要:策略模式實(shí)現(xiàn)的也是類似的場(chǎng)景。第二個(gè)部分是環(huán)境類不變,接收客戶的請(qǐng)求,隨后把請(qǐng)求委托給某一個(gè)策略類。參考文章設(shè)計(jì)模式設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐設(shè)計(jì)模式系統(tǒng)講解與應(yīng)用本文首發(fā),期待作者以樂(lè)之名本文原創(chuàng),有不當(dāng)?shù)牡胤綒g迎指出。 showImg(https://segmentfault.com/img/bVbugi7?w=800&h=600); 策略模式:定義一系列的算法,把它們一個(gè)個(gè)封裝起來(lái),并且...
摘要:本系列為設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐作者曾探學(xué)習(xí)總結(jié),如想深入了解,請(qǐng)支持作者原版策略模式策略模式的定義定義一系列的算法,把它們一個(gè)個(gè)封裝起來(lái),并且使它們可以互相替換。 本系列為《JavaScript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐》(作者:曾探)學(xué)習(xí)總結(jié),如想深入了解,請(qǐng)支持作者原版 策略模式 策略模式的定義:定義一系列的算法,把它們一個(gè)個(gè)封裝起來(lái),并且使它們可以互相替換。 舉個(gè)形象的例子,使用策略模式計(jì)算...
摘要:策略模式可以避免代碼中的多重判斷條件。策略模式在程序中或多或少的增加了策略類。此文僅記錄本人閱讀設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐這個(gè)本時(shí)的感受,感謝作者曾探寫(xiě)出這么好的一本書(shū)。設(shè)計(jì)模式中很重要的一點(diǎn)就是將不變和變分離出來(lái)。參考設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐曾探 策略模式的定義是:定義一系列的算法,把它們一個(gè)個(gè)封裝起來(lái),并且是它們可以相互替換。 策略模式可以避免代碼中的多重判斷條件。 策略模式很好的體現(xiàn)了開(kāi)放-...
摘要:設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐讀書(shū)筆記。策略模式可以有效避免多重條件選擇語(yǔ)句。當(dāng)然,策略模式也有一些缺點(diǎn)增加了許多策略類或者策略對(duì)象。要使用策略模式,必須了解所有的,違反了最少知識(shí)原則。至此,回家咯附設(shè)計(jì)模式之發(fā)布訂閱模式觀察者模式 《JavaScript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐》讀書(shū)筆記。這本書(shū)挺好的,推薦。 俗話說(shuō),條條大路通羅馬。在現(xiàn)實(shí)生活中,我們可以采用很多方法實(shí)現(xiàn)同一個(gè)目標(biāo)。比如我們先定個(gè)小目...
閱讀 2096·2021-11-23 09:51
閱讀 3378·2021-09-28 09:36
閱讀 1158·2021-09-08 09:35
閱讀 1816·2021-07-23 10:23
閱讀 3306·2019-08-30 15:54
閱讀 3026·2019-08-29 17:05
閱讀 472·2019-08-29 13:23
閱讀 1326·2019-08-28 17:51