JavaScript設(shè)計(jì)模式——策略模式

????策略模式的定義是:定義一系列的算法,把它們一個(gè)個(gè)封裝起來(lái),并且使它們可以相互替換。

????俗話說(shuō),條條大路通羅馬。在美劇《越獄》中,主角 Michael Scofield 就設(shè)計(jì)了兩條越獄的道路。這兩條道路都可以到達(dá)靠近監(jiān)獄外墻的醫(yī)務(wù)室。

????同樣,在現(xiàn)實(shí)中,很多時(shí)候也有多種途徑到達(dá)同一個(gè)目的地。比如我們要去某個(gè)地方旅游,可以根據(jù)具體的實(shí)際情況來(lái)選擇出行的線路。

????? 如果沒(méi)有時(shí)間但是不在乎錢,可以選擇坐飛機(jī)。

????? 如果沒(méi)有錢,可以選擇坐大巴或者火車。

????? 如果再窮一點(diǎn),可以選擇騎自行車。


????在程序設(shè)計(jì)中,我們也常常遇到類似的情況,要實(shí)現(xiàn)某一個(gè)功能有多種方案可以選擇。比如一個(gè)壓縮文件的程序,既可以選擇 zip 算法,也可以選擇 gzip 算法。

????這些算法靈活多樣,而且可以隨意互相替換。這種解決方案就是策略模式。

使用策略模式計(jì)算獎(jiǎng)金

????策略模式有著廣泛的應(yīng)用。我們以年終獎(jiǎng)的計(jì)算為例進(jìn)行介紹。

? ??很多公司的年終獎(jiǎng)是根據(jù)員工的工資基數(shù)和年底績(jī)效情況來(lái)發(fā)放的。例如,績(jī)效為 S 的人年終獎(jiǎng)有 4 倍工資,績(jī)效為 A 的人年終獎(jiǎng)有 3 倍工資,而績(jī)效為 B 的人年終獎(jiǎng)是 2 倍工資。假設(shè)財(cái)務(wù)部要求我們提供一段代碼,來(lái)方便他們計(jì)算員工的年終獎(jiǎng)。

1. 最初的代碼實(shí)現(xiàn)

????我們可以編寫一個(gè)名為 calculateBonus 的函數(shù)來(lái)計(jì)算每個(gè)人的獎(jiǎng)金數(shù)額。很顯然,calculateBonus 函數(shù)要正確工作,就需要接收兩個(gè)參數(shù):?jiǎn)T工的工資數(shù)額和他的績(jī)效考核等級(jí)。

代碼如下:

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

可以發(fā)現(xiàn),這段代碼十分簡(jiǎn)單,但是存在著顯而易見(jiàn)的缺點(diǎn)。

????? calculateBonus 函數(shù)比較龐大,包含了很多 if-else 語(yǔ)句,這些語(yǔ)句需要覆蓋所有的邏輯分支。

????? calculateBonus 函數(shù)缺乏彈性,如果增加了一種新的績(jī)效等級(jí) C,或者想把績(jī)效 S 的獎(jiǎng)金系數(shù)改為 5,那我們必須深入 calculateBonus 函數(shù)的內(nèi)部實(shí)現(xiàn),這是違反開(kāi)放?封閉原則的。

????? 算法的復(fù)用性差,如果在程序的其他地方需要重用這些計(jì)算獎(jiǎng)金的算法呢?我們的選擇只有復(fù)制和粘貼。

使用策略模式重構(gòu)代碼

????經(jīng)過(guò)思考,我們想到了更好的辦法——使用策略模式來(lái)重構(gòu)代碼。策略模式指的是定義一系列的算法,把它們一個(gè)個(gè)封裝起來(lái)。將不變的部分和變化的部分隔開(kāi)是每個(gè)設(shè)計(jì)模式的主題,策略模式也不例外,策略模式的目的就是將算法的使用與算法的實(shí)現(xiàn)分離開(kāi)來(lái)。

????在這個(gè)例子里,算法的使用方式是不變的,都是根據(jù)某個(gè)算法取得計(jì)算后的獎(jiǎng)金數(shù)額。而算法的實(shí)現(xiàn)是各異和變化的,每種績(jī)效對(duì)應(yīng)著不同的計(jì)算規(guī)則。

????一個(gè)基于策略模式的程序至少由兩部分組成。第一個(gè)部分是一組策略類,策略類封裝了具體的算法,并負(fù)責(zé)具體的計(jì)算過(guò)程。第二個(gè)部分是環(huán)境類 Context,Context 接受客戶的請(qǐng)求,隨后把請(qǐng)求委托給某一個(gè)策略類。要做到這點(diǎn),說(shuō)明 Context 中要維持對(duì)某個(gè)策略對(duì)象的引用。

????現(xiàn)在用策略模式來(lái)重構(gòu)上面的代碼。

// 策略對(duì)象

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 ) ); // 輸出:30000

策略模式的優(yōu)缺點(diǎn)

????策略模式是一種常用且有效的設(shè)計(jì)模式,策略模式的一些優(yōu)點(diǎn)。

????? 策略模式利用組合、委托和多態(tài)等技術(shù)和思想,可以有效地避免多重條件選擇語(yǔ)句。

????? 策略模式提供了對(duì)開(kāi)放—封閉原則的完美支持,將算法封裝在獨(dú)立的 strategy 中,使得它們易于切換,易于理解,易于擴(kuò)展。

????? 策略模式中的算法也可以復(fù)用在系統(tǒng)的其他地方,從而避免許多重復(fù)的復(fù)制粘貼工作。

????? 在策略模式中利用組合和委托來(lái)讓 Context 擁有執(zhí)行算法的能力,這也是繼承的一種更輕便的替代方案。

????當(dāng)然,策略模式也有一些缺點(diǎn),但這些缺點(diǎn)并不嚴(yán)重。

????首先,使用策略模式會(huì)在程序中增加許多策略類或者策略對(duì)象,但實(shí)際上這比把它們負(fù)責(zé)的邏輯堆砌在 Context 中要好。

????其次,要使用策略模式,必須了解所有的 strategy,必須了解各個(gè) strategy 之間的不同點(diǎn),這樣才能選擇一個(gè)合適的 strategy。比如,我們要選擇一種合適的旅游出行路線,必須先了解選擇飛機(jī)、火車、自行車等方案的細(xì)節(jié)。此時(shí) strategy 要向客戶暴露它的所有實(shí)現(xiàn),這是違反最少知識(shí)原則的。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ——摘自《JavaScript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐 》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 工廠模式類似于現(xiàn)實(shí)生活中的工廠可以產(chǎn)生大量相似的商品,去做同樣的事情,實(shí)現(xiàn)同樣的效果;這時(shí)候需要使用工廠模式。簡(jiǎn)單...
    舟漁行舟閱讀 8,130評(píng)論 2 17
  • 轉(zhuǎn)載:https://www.cnblogs.com/tugenhua0707/p/4722696.html理解j...
    Picidae閱讀 378評(píng)論 0 1
  • 1、策略模式的定義是: 定義一系列的算法, 把它們一個(gè)個(gè)封裝起來(lái), 并且使它們可以相互替換。 不變的部分和變化的部...
    spfi閱讀 1,312評(píng)論 0 100
  • 策略模式的定義:定義一系列的算法,把它們一個(gè)個(gè)封裝起來(lái),并且使它們可以相互替換。 將不變的部分和變化的部分隔開(kāi)是每...
    peppermint_egg閱讀 1,619評(píng)論 0 0
  • 偶然的機(jī)會(huì)認(rèn)識(shí)的簡(jiǎn)書,便喜歡上這兒??梢詫W(xué)習(xí),可以發(fā)表,可以互動(dòng),雖然初來(lái)乍到,沒(méi)認(rèn)識(shí)幾個(gè)人,還是興致盎然的寫著,...
    sun靜待花開(kāi)閱讀 132評(píng)論 0 2

友情鏈接更多精彩內(nèi)容