摘要:策略模式的優(yōu)缺點(diǎn)優(yōu)點(diǎn)策略模式利用組合,委托和多態(tài)等技術(shù)思想,可以有效避免多重條件選擇語句。策略模式提供了對開放封閉原則的完美支持。策略模式會(huì)向用戶暴露所有實(shí)現(xiàn)細(xì)節(jié),這其實(shí)是違反最少知識(shí)原則。
策略模式的定義是:定義一系列的算法,把它們一個(gè)個(gè)封裝起來,并且使它們可以相互替換。
在現(xiàn)實(shí)中,如果我們想去某個(gè)地方旅游,可以根據(jù)實(shí)際情況有多種路線
如果沒有時(shí)間但是不在乎錢,可以選擇飛機(jī)
如果沒有錢,可以選擇大巴活著火車
如果再窮一點(diǎn),可以選擇騎自行車
使用策略模式計(jì)算獎(jiǎng)金現(xiàn)在以年終獎(jiǎng)的計(jì)算為例
公司年終獎(jiǎng)根據(jù)員工的工資基數(shù)和年底績效來發(fā)放
績效S,四倍年終獎(jiǎng)
績效A,三倍年終獎(jiǎng)
績效B,二倍年終獎(jiǎng)
最初的實(shí)現(xiàn)var calculateBonus = function(performanceLevel, salary) { if (performanceLevel === "S") { return salary*4 } if (performanceLevel === "A") { return salary*3 } if (performanceLevel === "B") { return salary*2 } } calculateBonus("B", 2000) // 4000 calculateBonus("S", 2000) // 8000
這段代碼簡單,但是存在顯而易見的缺點(diǎn)
函數(shù)比較龐大,包含很多if-else語句,這些語句需要覆蓋所有的邏輯分支
缺乏彈性,如果想新增績效C,就得深入函數(shù)內(nèi)部實(shí)現(xiàn),違反開放-封閉原則
算法的復(fù)用性差
策略模式的實(shí)現(xiàn)var strategies = { "S": function(salary) { return salary * 4 }, "A": function(salary) { return salary * 3 }, "B": function(salary) { return salary * 2 } } var calculateBonus = function(level, salary) { return strategies[level](salary) } console.log(calculateBonus("S", 2000)) // 8000 console.log(calculateBonus("B", 2000)) // 4000
通過使用策略模式重構(gòu)代碼,消除來原程序中分支語句。所有計(jì)算獎(jiǎng)金有關(guān)的邏輯分布在策略對象中,每個(gè)策略對象的算法已被各自封裝在對象內(nèi)部,當(dāng)我們對這些策略對象發(fā)出“計(jì)算獎(jiǎng)金”的請求時(shí),它們會(huì)返回各自的計(jì)算結(jié)果,這不僅是多態(tài)性的體現(xiàn),也是“自由交換”的目的。
使用策略模式實(shí)現(xiàn)緩動(dòng)動(dòng)畫用策略模式實(shí)現(xiàn)表單驗(yàn)證 我說div
從定義上看,策略模式就是用來封裝算法的。但是如果僅僅用來封裝算法,未免有點(diǎn)大材小用。在實(shí)際業(yè)務(wù)中,策略模式也可以用來封裝一系列的“業(yè)務(wù)規(guī)則”。只要業(yè)務(wù)規(guī)則指向的目標(biāo)一致,并且可以被替換使用,我們就可以用策略模式來封裝它們。
普通版本的表單驗(yàn)證這是一種很常見的編碼方式,可以看到缺點(diǎn)和計(jì)算獎(jiǎng)金一摸一樣
用策略模式重構(gòu)表單驗(yàn)證很明顯第一步我們需要將驗(yàn)證邏輯封裝成策略對象
var strategies = { isNonEmpty: function(value, errorMsg) { if (value === "") { return errorMsg } }, minLength: function(value, length, errorMsg) { if (value.length < length) { return errorMsg } }, isMobile: function(value, errorMsg) { if (!/(^1[3|5|8][0-9]{9}$)/.test(value)) { return errorMsg } } }
接下來實(shí)現(xiàn)Validator類,負(fù)責(zé)接受用戶的請求并委托給strategies
var Validator = function() { //保存校驗(yàn)規(guī)則 this.cache = [] } // 添加校驗(yàn) Validator.prototype.add = function(dom, rules) { var self = this // 遍歷校驗(yàn)規(guī)則 for(var i = 0, rule; rule = rules[i++];) { (function(rule){ //把strategy和參數(shù)分開 var strategyAry = rule.strategy.split(":") var errorMsg = rule.errorMsg // 把校驗(yàn)的步驟用空函數(shù)包裝起來,并且放入cache self.cache.push(function(){ // 挑選出校驗(yàn)規(guī)則 var strategy = strategyAry.shift() // 把input的value添加進(jìn)參數(shù)列表 strategyAry.unshift(dom.value) // 把errorMsg添加進(jìn)參數(shù)列表 strategyAry.push(errorMsg) return strategies[strategy].apply(dom, strategyAry) }) })(rule) } } // 啟動(dòng)校驗(yàn) Validator.prototype.start = function() { for (var i = 0, validatorFunc; validatorFunc = this.cache[i++];) { // 開始校驗(yàn),并取得校驗(yàn)后的結(jié)果 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: "isNonEmpty", errorMsg: "用戶名不能為空" }, { strategy: "minLength:10", errorMsg: "用戶名長度不能小于10位" } ] ) validator.add(registerForm.password, [ { strategy: "minLength:6", errorMsg: "密碼長度不能小于6位" } ] ) validator.add(registerForm.phonenumber, [ { strategy: "isMobile", errorMsg: "手機(jī)號(hào)碼格式不正確" } ] ) var errorMsg = validator.start() return errorMsg } var sub = document.querySelector("input[type="submit"]") sub.onclick = function() { var errorMsg = validataFunc() if (errorMsg) { console.error(errorMsg) return false } }
使用策略模式重構(gòu)代碼之后,我們不僅通過“配置”的方式就可以完成一個(gè)表單的校驗(yàn),這些規(guī)則也可以復(fù)用在程序的任何地方,還能以插件的形式,方便地移植到其他項(xiàng)目中。并且新增或者修改規(guī)則也是毫不費(fèi)力的。
策略模式的優(yōu)缺點(diǎn) 優(yōu)點(diǎn)策略模式利用組合,委托和多態(tài)等技術(shù)思想,可以有效避免多重條件選擇語句。
策略模式提供了對開放-封閉原則的完美支持。將算法封裝在獨(dú)立的strategy中,使得它們易于切換,易于理解,易于擴(kuò)展。
策略模式中的算法也可以復(fù)用在系統(tǒng)中的其他地方。
在策略模式中利用組合和委托讓Content擁有執(zhí)行算法的能力,這也是繼承的一種更輕便的替代方案。
缺點(diǎn)使用策略對象會(huì)增加很多策略類或者策略對象,但實(shí)際上比把這些邏輯放在Content更好。
策略模式會(huì)向用戶暴露所有實(shí)現(xiàn)細(xì)節(jié),這其實(shí)是違反最少知識(shí)原則。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/99180.html
摘要:做前端開發(fā)已經(jīng)好幾年了,對設(shè)計(jì)模式一直沒有深入學(xué)習(xí)總結(jié)過。今天第一天,首先來講策略模式。什么是策略模式四兄弟的經(jīng)典設(shè)計(jì)模式中,對策略模式的定義如下定義一系列的算法,把它們一個(gè)個(gè)封裝起來,并且使它們可互相替換。 做前端開發(fā)已經(jīng)好幾年了,對設(shè)計(jì)模式一直沒有深入學(xué)習(xí)總結(jié)過。隨著架構(gòu)相關(guān)的工作越來越多,越來越能感覺到設(shè)計(jì)模式成為了我前進(jìn)道路上的一個(gè)阻礙。所以從今天開始深入學(xué)習(xí)和總結(jié)經(jīng)典的設(shè)計(jì)模...
摘要:函數(shù)式編程前端掘金引言面向?qū)ο缶幊桃恢币詠矶际侵械闹鲗?dǎo)范式。函數(shù)式編程是一種強(qiáng)調(diào)減少對程序外部狀態(tài)產(chǎn)生改變的方式。 JavaScript 函數(shù)式編程 - 前端 - 掘金引言 面向?qū)ο缶幊桃恢币詠矶际荍avaScript中的主導(dǎo)范式。JavaScript作為一門多范式編程語言,然而,近幾年,函數(shù)式編程越來越多得受到開發(fā)者的青睞。函數(shù)式編程是一種強(qiáng)調(diào)減少對程序外部狀態(tài)產(chǎn)生改變的方式。因此,...
摘要:單體模式有以下優(yōu)點(diǎn)用來劃分命名空間,減少全局變量數(shù)量。通常我們使用操作符創(chuàng)建單體模式的三種選擇,讓構(gòu)造函數(shù)總返回最初的對象使用全局對象來存儲(chǔ)該實(shí)例不推薦,容易全局污染。實(shí)現(xiàn)該工廠模式并不困難,主要是要找到能夠穿件所需類型對象的構(gòu)造函數(shù)。 介紹 最近開始給自己每周訂個(gè)學(xué)習(xí)任務(wù),學(xué)習(xí)結(jié)果反饋為一篇文章的輸出,做好學(xué)習(xí)記錄。 這一周(02.25-03.03)我定的目標(biāo)是《JavaScri...
摘要:實(shí)際上在這種將函數(shù)作為一等對象的語言里,策略模式已經(jīng)融入到了語言本身當(dāng)中,我們經(jīng)常使用高階函數(shù)來封裝不同的行為,并且把它傳遞到另一個(gè)函數(shù)中。 聲明:這個(gè)系列為閱讀《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》 ----曾探@著一書的讀書筆記 1.策略模式的定義 將不變的部分和變化的部分隔開是每個(gè)設(shè)計(jì)模式的主題。 定義一系列的算法,把它們一個(gè)個(gè)封裝起來,并且使它們可以相互替換。 2.策略模式...
摘要:策略模式實(shí)現(xiàn)的也是類似的場景。第二個(gè)部分是環(huán)境類不變,接收客戶的請求,隨后把請求委托給某一個(gè)策略類。參考文章設(shè)計(jì)模式設(shè)計(jì)模式與開發(fā)實(shí)踐設(shè)計(jì)模式系統(tǒng)講解與應(yīng)用本文首發(fā),期待作者以樂之名本文原創(chuàng),有不當(dāng)?shù)牡胤綒g迎指出。 showImg(https://segmentfault.com/img/bVbugi7?w=800&h=600); 策略模式:定義一系列的算法,把它們一個(gè)個(gè)封裝起來,并且...
閱讀 3325·2021-11-12 10:36
閱讀 2483·2021-11-02 14:43
閱讀 2156·2019-08-30 14:23
閱讀 3471·2019-08-30 13:08
閱讀 928·2019-08-28 18:09
閱讀 3141·2019-08-26 12:22
閱讀 3155·2019-08-23 18:24
閱讀 2025·2019-08-23 18:17