摘要:將不變的部分和變化的部分隔開是每個設計模式的主題,策略模式也不例外,策略模式的目的就是將算法的使用與算法的實現(xiàn)分離開來。
前言
本系列文章主要根據(jù)《JavaScript設計模式與開發(fā)實踐》整理而來,其中會加入了一些自己的思考。希望對大家有所幫助。
文章系列js設計模式--單例模式
js設計模式--策略模式
js設計模式--代理模式
概念策略模式的定義是:定義一系列的算法,把它們一個個封裝起來,并且使它們可以相互替換。
策略模式指的是定義一系列的算法,把它們一個個封裝起來。將不變的部分和變化的部分隔開是每個設計模式的主題,策略模式也不例外,策略模式的目的就是將算法的使用與算法的實現(xiàn)分離開來。
一個基于策略模式的程序至少由兩部分組成。第一個部分是一組策略類,策略類封裝了具體 的算法,并負責具體的計算過程。 第二個部分是環(huán)境類Context,Context 接受客戶的請求,隨后 把請求委托給某一個策略類。要做到這點,說明 Context中要維持對某個策略對象的引用。
策略模式的實現(xiàn)并不復雜,關鍵是如何從策略模式的實現(xiàn)背后,找到封裝變化、委托和多態(tài)性這些思想的價值。
場景從定義上看,策略模式就是用來封裝算法的。但如果把策略模式僅僅用來封裝算法,未免有一點大材小用。在實際開發(fā)中,我們通常會把算法的含義擴散開來,使策略模式也可以用來封裝 一系列的“業(yè)務規(guī)則”。只要這些業(yè)務規(guī)則指向的目標一致,并且可以被替換使用,我們就可以 用策略模式來封裝它們。
優(yōu)缺點 優(yōu)點策略模式利用組合、委托和多態(tài)等技術和思想,可以有效地避免多重條件選擇語句。
策略模式提供了對開放—封閉原則的完美支持,將算法封裝在獨立的strategy中,使得它們易于切換,易于理解,易于擴展。
策略模式中的算法也可以復用在系統(tǒng)的其他地方,從而避免許多重復的復制粘貼工作。
在策略模式中利用組合和委托來讓 Context 擁有執(zhí)行算法的能力,這也是繼承的一種更輕便的替代方案。
缺點增加許多策略類或者策略對象,但實際上這比把它們負責的 邏輯堆砌在 Context 中要好。
要使用策略模式,必須了解所有的 strategy,必須了解各個 strategy 之間的不同點, 這樣才能選擇一個合適的 strategy。
但這些缺點并不嚴重
例子 計算獎金 粗糙的實現(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", 20000 ); // 輸出:40000 calculateBonus( "S", 6000 ); // 輸出:24000
缺點:
calculateBonus 函數(shù)比較龐大,包含了很多 if-else 語句
calculateBonus 函數(shù)缺乏彈性,如果增加了一種新的績效等級 C,或者想把績效 S 的獎金 系數(shù)改為 5,那我們必須深入 calculateBonus 函數(shù)的內部實現(xiàn),這是違反開放?封閉原則的。
算法的復用性差
使用組合函數(shù)重構代碼var performanceS = function( salary ){ return salary * 4; }; var performanceA = function( salary ){ return salary * 3; }; var performanceB = function( salary ){ return salary * 2; }; var calculateBonus = function( performanceLevel, salary ){ if ( performanceLevel === "S" ){ return performanceS( salary ); } if ( performanceLevel === "A" ){ return performanceA( salary ); } if ( performanceLevel === "B" ){ return performanceB( salary ); } }; calculateBonus( "A" , 10000 ); // 輸出:30000
問題依然存在:calculateBonus 函數(shù)有可能越來越龐大,而且在系統(tǒ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; }; //接下來定義獎金類Bonus: var Bonus = function(){ this.salary = null; // 原始工資 this.strategy = null; // 績效等級對應的策略對象 }; Bonus.prototype.setSalary = function( salary ){ this.salary = salary; // 設置員工的原始工資 }; Bonus.prototype.setStrategy = function( strategy ){ this.strategy = strategy; // 設置員工績效等級對應的策略對象 }; Bonus.prototype.getBonus = function(){ // 取得獎金數(shù)額 return this.strategy.calculate( this.salary ); // 把計算獎金的操作委托給對應的策略對象 }; var bonus = new Bonus(); bonus.setSalary( 10000 ); bonus.setStrategy( new performanceS() ); // 設置策略對象 console.log( bonus.getBonus() ); // 輸出:40000 bonus.setStrategy( new performanceA() ); // 設置策略對象 console.log( bonus.getBonus() ); // 輸出:30000
但這段代碼是基于傳統(tǒng)面向對象語言的模仿,下面我們用JavaScript實現(xiàn)的策略模式。
JavaScript 版本的策略模式在 JavaScript 語言中,函數(shù)也是對象,所以更簡單和直接的做法是把 strategy 直接定義為函數(shù)
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", 20000 ) ); // 輸出:80000 console.log( calculateBonus( "A", 10000 ) ); // 輸出:30000es6類實現(xiàn)
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; }; //接下來定義獎金類Bonus: class Bonus { constructor() { this.salary = null; // 原始工資 this.strategy = null; // 績效等級對應的策略對象 } setSalary(salary) { this.salary = salary; // 設置員工的原始工資 } setStrategy(strategy) { this.strategy = strategy; // 設置員工績效等級對應的策略對象 } getBonus() { // 取得獎金數(shù)額 return this.strategy.calculate(this.salary); // 把計算獎金的操作委托給對應的策略對象 } } var bonus = new Bonus(); bonus.setSalary(10000); bonus.setStrategy(new performanceS()); // 設置策略對象 console.log(bonus.getBonus()); // 輸出:40000 bonus.setStrategy(new performanceA()); // 設置策略對象 console.log(bonus.getBonus()); // 輸出:30000緩動動畫 目標:編寫一個動畫類和一些緩動算法,讓小球以各種各樣的緩動效果在頁面中運動 分析:
首先緩動算法的職責是實現(xiàn)小球如何運動
然后動畫類(即context)的職責是負責:
初始化動畫對象
在運動開始之前,需要提前記錄一些有用的信息,至少包括以下信息:
動畫開始時的準確時間點;
動畫開始時,小球所在的原始位置;
小球移動的目標位置;
小球運動持續(xù)的時間。
計算小球某時刻的位置
更新小球的位置
實現(xiàn):驗證表單 簡單的實現(xiàn)Document 我是div
使用策略模式改進
缺點:一 個文本輸入框只能對應一種校驗規(guī)則
再改進:可以有多個校驗規(guī)則文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100630.html
摘要:策略模式定義一系列的算法把它們一個個封裝起來并且使它們可相互替換。策略模式要素策略接口,用來約束一系列具體的策略算法。策略模式策略購買輛總金額策略購買輛總金額策略模式優(yōu)點算法可以自由切換。策略模式缺點策略類會增多。所有策略類都需要對外暴露。 策略模式 定義一系列的算法,把它們一個個封裝起來, 并且使它們可相互替換。本模式使得算法可獨立于使用它的客戶而變化。策略模式是把一個類中經(jīng)常改變或...
摘要:策略模式可以避免代碼中的多重判斷條件。策略模式在程序中或多或少的增加了策略類。此文僅記錄本人閱讀設計模式與開發(fā)實踐這個本時的感受,感謝作者曾探寫出這么好的一本書。設計模式中很重要的一點就是將不變和變分離出來。參考設計模式與開發(fā)實踐曾探 策略模式的定義是:定義一系列的算法,把它們一個個封裝起來,并且是它們可以相互替換。 策略模式可以避免代碼中的多重判斷條件。 策略模式很好的體現(xiàn)了開放-...
摘要:版本策略模式在上個例子中雖然初步實現(xiàn)了策略模式,但是是仿照的傳統(tǒng)面向對象語言,而的實現(xiàn)更為簡單,直接把原來的實例定義成函數(shù),原先的類用函數(shù)來委托。 1. 介紹 策略模式是JS設計模式中一大重要的模式有著廣泛的應用 2. 定義 定義一系列的算法,把它們一個個封裝起來,并且使它們可以相互替換 3. 應用 根據(jù)等級、工資計算獎金等類似情況、使用不同的動畫效果、表單驗證等 4. 思想 把算法實...
摘要:策略模式又稱政策模式,其定義一系列的算法,把它們一個個封裝起來,并且使它們可以互相替換。的表單具有表單驗證功能,用來校驗用戶輸入的表單內容。實際需求中表單驗證項一般會比較復雜,所以需要給每個表單項增加自定義校驗方法。 showImg(https://segmentfault.com/img/remote/1460000020135990); 策略模式 (Strategy Pattern...
摘要:策略模式是指對一系列的算法定義,并將每一個算法封裝起來,而且使它們還可以相互替換。策略模式讓算法獨立于使用它的客戶而獨立變化。 策略模式是指對一系列的算法定義,并將每一個算法封裝起來,而且使它們還可以相互替換。策略模式讓算法獨立于使用它的客戶而獨立變化。 優(yōu)點: 策略模式利用組合、委托等技術和思想,可以避免很多if條件語句 策略模式提供了開放-封閉原則,使代碼更容易理解和拓展 簡單...
閱讀 3778·2021-11-23 09:51
閱讀 4413·2021-11-15 11:37
閱讀 3526·2021-09-02 15:21
閱讀 2750·2021-09-01 10:31
閱讀 882·2021-08-31 14:19
閱讀 859·2021-08-11 11:20
閱讀 3313·2021-07-30 15:30
閱讀 1695·2019-08-30 15:54