話說js設計模式有關的書籍有Ross Harmes / Dustin Diaz 的《Javascript設計模式》,Stoyan Stefanov的《JavaScript Patterns》,Addy Osmani的《Learning JavaScript Design Patterns》。
第一本很早就出來了,比較古老,基本上內容就是,js類比物件導向語言,再把物件導向的設計模式套進來。
話說,設計模式是一種思想,物件導向語言,函數式語言都能以自己的方式演繹。
第二本,第三本就比較實在了,不那麼崇拜物件導向了,雖然還是有點物件導向。
設計模式的入門書國人寫的《大話設計模式》,很受用。這本書代碼用C#演繹。
於是,決定把那本書的代碼用javascript語言演繹,且用裡面的設計模式思想。
今天就來說說策略模式吧。
原文是寫,商場收銀軟體的實現。正常收費,打折收費,滿xx返xx。
符合現實情況。產品人員,動不動跑過來說,有新需求,來來,給哥加個新功能。
面對不斷變化和增加的需求,如何使自己的原先代碼改動成本更小,這時候設計模式派上用場了。
話說,我實在看不出來策略模式和簡單原廠模式有啥區別,因為我覺得它們都是同樣的過程產生的模式。
直到,看到,後面,說,用簡單原廠模式,用戶端要認識兩個類;用策略模式和簡單原廠模式結合,用戶端只認識一個類。
我頓時被雷到了。外焦裡嫩了。
我覺得設計模式的表現,就是改寫程式設計語言的預設調用方式。
至於各種模式,所展現的思想,都能以一個過程展示。這就是萬變不離其宗吧。
好了,下面代碼展示我的策略模式,其中還有函數式寫法。
只要腦子裡想著一個原則,把重複抽象出來,大重複基於小重複,應該就能寫出和設計模式媲美的代碼了,嘻嘻:
<!DOCTYPE html><html><head> <meta charset="utf-8" /> <title>策略模式</title> <script type="text/javascript">
// 打折收費,基於正常收費;滿多少返多少收費,基於正常收費;打折收費結合滿多少返多少收費,基於你懂的。 // 正常收費 function cash_normal(price_arg,num_arg) { return price_arg * num_arg; } // 打折收費 function cash_rebate(money_arg,rebate_arg){ return money_arg * rebate_arg; } // 滿xx返xx function cash_return(money_input_arg,money_condition_arg, money_return_arg){ if(money_input_arg > money_condition_arg){ return money_input_arg - money_return_arg; } else{ return money_input_arg; } } // function cash_normal_rebate(price_arg, num_arg, rebate_arg){ return cash_rebate(cash_normal(price_arg,num_arg),rebate_arg); } function cash_normal_rebate_return(price_arg, num_arg, rebate_arg, money_condition_arg, money_return_arg){ return cash_return(cash_normal_rebate(price_arg,num_arg,rebate_arg),money_condition_arg,money_return_arg) } var number = 10; var price = 10; console.log("打八折:買"+number+"個,"+price+"元的東西"+cash_normal_rebate(number,price,0.8)); console.log("打八折,滿50返10元:"+cash_normal_rebate_return(price,number,0.8,50,10)); // 函數式寫法 function tao(){ return tao; } function cash_normal2(price_arg,num_arg){ return function(handle_func){ var total_money = price_arg * num_arg; if(handle_func){ return handle_func(total_money); } else{ return tao; } }; } function crsh_rebate_factory(rebate_arg){ return function(total_money){ // var total_money = rebate_arg*total_money; return function(handle_func){ var discount_money = rebate_arg * total_money; if(handle_func){ return handle_func(discount_money,rebate_arg); } else{ return tao; } }; }; } function show_money(total_money,rebate_arg){ return function(handle_func){ console.log("函數式寫法,乘以"+rebate_arg+":" + total_money); if(handle_func){ return handle_func(total_money); } else{ return tao; } } } cash_normal2(10,10)(crsh_rebate_factory(0.8))(show_money)(); </script></head><body> </body></html>
函數式寫法有意思的地方在於,參數是函數,返回的是函數。完成一個任務,只要不斷調用函數就行了,是橫向。
而主流抽象方法是,大函數,用到小函數的話,得把小函數的參數,放進大函數的參數列表裡面。
設計模式裡有一個依賴倒轉原則,對於,大函數依賴小函數,不是非常認可。無論大函數,還是小函數都要依賴抽象。我個人認為,那個抽象就是指代碼注釋,或文檔了。