自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

新生代農(nóng)民工需要懂的策略設(shè)計(jì)模式

開發(fā) 前端
俗話說,凡事講策略。講策略的時(shí)候,我們往往會(huì)考慮每種情況的成本。策略同樣可體現(xiàn)在我們的代碼之中,合理利用策略模式重構(gòu)邏輯復(fù)雜的代碼,會(huì)使項(xiàng)目工程更易維護(hù)和擴(kuò)展。

[[418571]]

本文轉(zhuǎn)載自微信公眾號(hào)「DYBOY」,作者DYBOY 。轉(zhuǎn)載本文請(qǐng)聯(lián)系DYBOY公眾號(hào)。

俗話說,凡事講策略。講策略的時(shí)候,我們往往會(huì)考慮每種情況的成本。策略同樣可體現(xiàn)在我們的代碼之中,合理利用策略模式重構(gòu)邏輯復(fù)雜的代碼,會(huì)使項(xiàng)目工程更易維護(hù)和擴(kuò)展。

這幾天朋友圈被“新生代農(nóng)民工”刷屏了,看到有這樣一張截圖:

新生代農(nóng)民工正名

代碼里寫了約 30 個(gè) if else 邏輯,從程序語(yǔ)義以及程序效率理論上是會(huì)有一定的影響,最主要的是可能會(huì)被其他“新生代農(nóng)民工”嘲笑。

一位經(jīng)驗(yàn)老道的民工則會(huì)用一手 switch case 或策略模式來重構(gòu)代碼,那么什么是策略模式吶?

一、定義

策略:為實(shí)現(xiàn)一定的戰(zhàn)略任務(wù),根據(jù)形勢(shì)發(fā)展而制定的行動(dòng)方針和斗爭(zhēng)方式。

策略模式:一種行為設(shè)計(jì)模式,它能讓你定義一系列算法,并將每種算法分別放入獨(dú)立的類中,以使算法的對(duì)象能夠相互替換。

在常見的前端游戲獎(jiǎng)勵(lì)激勵(lì)交互中,常常會(huì)涉及到不同分?jǐn)?shù)會(huì)展示不同的動(dòng)效,這其實(shí)就是一種條件策略。

二、優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

  • 隔離算法的實(shí)現(xiàn)與使用
  • 運(yùn)行時(shí)可切換算法
  • 用組合代替繼承
  • 易擴(kuò)展,符合開閉原則,無需修改上下文即可引入新策略

缺點(diǎn):

  • 需要暴露所有的策略接口,用于區(qū)分策略差異
  • 如果邏輯條件簡(jiǎn)單,使用策略模式會(huì)增加代碼冗余度

三、實(shí)現(xiàn)

策略模式指的是定義了一系例算法,把它們每個(gè)都封裝起來。將不變的部分和變化的部分隔離開來是設(shè)計(jì)模式中的一個(gè)重要思想,策略模式則是將算法和使用算法兩部分的實(shí)現(xiàn)拆開,降低耦合度。

基于策略模式的程序至少有兩部分組成:策略類和環(huán)境類(Context)。

策略類封裝了具體的算法,并負(fù)責(zé)具體的計(jì)算過程,可以理解為“執(zhí)行者”。

環(huán)境類(Context)接受客戶的請(qǐng)求,然后將請(qǐng)求委托給一個(gè)策略類,可以理解為“調(diào)度者”。

四、表單驗(yàn)證中的策略模式

在Web項(xiàng)目中,常見的表單有注冊(cè)、登陸、修改用戶信息等涉及到表單的功能,與此同時(shí)我們會(huì)在表單提交的時(shí)候,做一些例的前端輸入框值的條件校驗(yàn)工作。

由于輸入框中用戶的輸入是任意的,校驗(yàn)的規(guī)則相對(duì)比較復(fù)雜,如果不使用設(shè)計(jì)模式,我們的代碼中可能就會(huì)寫出較多的 if else 判斷邏輯,從可閱讀性和可維護(hù)性來說,確實(shí)不是很好。

接下來我們將從前端Web項(xiàng)目中常見的表單驗(yàn)證功能,逐步認(rèn)識(shí)策略設(shè)計(jì)模式。

4.1 初級(jí)的表單驗(yàn)證

在很久很久以前,我的表單驗(yàn)證可能是這么寫的:

  1. var username = $('#nuserame').val(); 
  2. var password = $('#password').val(); 
  3.  
  4. if (!username) { 
  5.     alert('用戶名不能為空'); 
  6. else if (username.length < 5) { 
  7.     alert('用戶名長(zhǎng)度需要大于等于5'); 
  8. else if (username.length < 13) { 
  9.     alert('用戶名長(zhǎng)度需要小于13'); 
  10. else if (!(/[a-z]+/i.test(username))) { 
  11.     alert('用戶名只能包含英文大小寫字符'
  12. else { 
  13.     regeister(username); 
  14.  
  15. // password的驗(yàn)證同上 

寫法似乎有些不忍直視,不過能用!

4.2 基于策略模式的表單驗(yàn)證

換個(gè)思路,結(jié)合策略模式的思想,實(shí)現(xiàn)一個(gè)專用于值校驗(yàn)的 Validator 類,Validator 是一個(gè)調(diào)度著,也就是策略模式中的環(huán)境類。

然后我們?cè)隍?yàn)證目標(biāo)字段值 targetValue 的時(shí)候其用法大致如下:

  1. Validator.addRules(targetValue, ['isNonEmpty''minLength:5''maxLength:12']).valid(); 

校驗(yàn)器會(huì)返回判斷結(jié)果 result 字段,以及語(yǔ)義話的提示 msg 字段:

  1. return { 
  2.     result: false
  3.     msg: '不能為空' 

4.2.1 Validator

根據(jù)上述需求,Validator的實(shí)現(xiàn)如下:

  1. const formatResult = (isPass: boolean = false, errMsg: string = "") => { 
  2.   return { 
  3.     result: isPass, 
  4.     msg: errMsg, 
  5.   }; 
  6. }; 
  7.  
  8. const ValidStrategies = { 
  9.   isNonEmpty: function (val: string = "") { 
  10.     if (!val) return formatResult(false"內(nèi)容不能為空"); 
  11.   }, 
  12.   minLength: function (val: string = "", length: string | number = 0) { 
  13.     console.log(val, length); 
  14.     if (typeof length === "string") length = parseInt(length); 
  15.     if (val.length < length) 
  16.       return formatResult(false, `內(nèi)容長(zhǎng)度不能小于${length}`); 
  17.   }, 
  18.   maxLength: function (val: string = "", length: string | number = 0) { 
  19.     if (typeof length === "string") length = parseInt(length); 
  20.     if (val.length > length) 
  21.       return formatResult(false, `內(nèi)容長(zhǎng)度不能大于${length}`); 
  22.   }, 
  23.   defaultfunction () { 
  24.     return formatResult(true); 
  25.   }, 
  26. }; 
  27.  
  28. /** 
  29.  * 驗(yàn)證器 
  30.  * 策略模式 —— 環(huán)境類,負(fù)責(zé)調(diào)度算法 
  31.  */ 
  32. class Validator { 
  33.   // 存儲(chǔ)規(guī)則 
  34.   private _ruleExecuters: Array<any>; 
  35.  
  36.   constructor() { 
  37.     this._ruleExecuters = []; 
  38.   } 
  39.  
  40.   /** 
  41.    * addRules 
  42.    * 添加校驗(yàn)規(guī)則 
  43.    */ 
  44.   public addRules(value: string = "", rules: Array<string>) { 
  45.     this._ruleExecuters = []; 
  46.     rules.forEach((rule) => { 
  47.       const args = rule.split(":"); 
  48.       const functionName = args.shift() || "default"
  49.       // 忽略下這里的斷言類型👀 
  50.       const ruleFunc = ValidStrategies[ 
  51.         functionName as "isNonEmpty" | "minLength" | "maxLength" | "default" 
  52.       ].bind(this, value); 
  53.       this._ruleExecuters.push({ 
  54.         func: ruleFunc, 
  55.         args, 
  56.       }); 
  57.     }); 
  58.     return this; 
  59.   } 
  60.  
  61.   /** 
  62.    * valid 
  63.    */ 
  64.   public valid() { 
  65.     for (let i = 0; i < this._ruleExecuters.length; i++) { 
  66.       const res = this._ruleExecuters[i].func.apply( 
  67.         this, 
  68.         this._ruleExecuters[i].args 
  69.       ); 
  70.       if (res && !res.result) { 
  71.         return res; 
  72.       } 
  73.     } 
  74.     return formatResult(true); 
  75.   } 
  76.  
  77. export default new Validator(); 
  1. const res = Validator.addRules("123", [ 
  2.     "isNonEmpty"
  3.     "minLength:5"
  4.     "maxLength:12"
  5.   ]).valid(); 
  6.   console.log("res:", res); 

執(zhí)行結(jié)果

這樣在驗(yàn)證表單值的時(shí)候,我們就可以直接調(diào)用 Validator 驗(yàn)證值的合法性。

與此同時(shí),還可以通過擴(kuò)展策略類(對(duì)象)ValidStrategies 中的驗(yàn)證算法來擴(kuò)展校驗(yàn)器的能力。

五、表驅(qū)動(dòng)法

策略模式節(jié)省邏輯判斷的特性讓我聯(lián)想到了之前看過的一個(gè)概念“表驅(qū)動(dòng)法”,或者叫“查表法”,這里引用下百度百科的解釋:

表驅(qū)動(dòng)方法出于特定的目的來使用表,程序員們經(jīng)常談到“表驅(qū)動(dòng)”方法,但是課本中卻從未提到過什么是"表驅(qū)動(dòng)"方法。表驅(qū)動(dòng)方法是一種使你可以在表中查找信息,而不必用很多的邏輯語(yǔ)句(if 或 Case)來把它們找出來的方法。事實(shí)上,任何信息都可以通過表來挑選。在簡(jiǎn)單的情況下,邏輯語(yǔ)句往往更簡(jiǎn)單而且更直接。但隨著邏輯鏈的復(fù)雜,表就變得越來越富有吸引力了。

舉個(gè)例子,假設(shè)我們想要獲取當(dāng)前是星期幾,代碼可能是這樣的:

  1. function getDay() { 
  2.   const day = (new Date()).getDay(); 
  3.   switch (day) { 
  4.     case 0: 
  5.       return '星期日'
  6.     case 1: 
  7.       return '星期一'
  8.     // ... 
  9.     case 6: 
  10.       return '星期六'
  11.     default
  12.       return ''
  13.   } 

如果是初次編程的同學(xué)還可能會(huì)有 if else 條件語(yǔ)句來判斷返回值,代碼就會(huì)顯得比較冗余。

借助表驅(qū)動(dòng)發(fā)法的思想,這里我們是可以有優(yōu)化空間的,表驅(qū)動(dòng)發(fā)法的寫法如下:

  1. const days = ['星期日''星期一''星期二''星期三''星期四''星期五''星期六']; 
  2. function getDay2() { 
  3.   return days[(new Date()).getDay()]; 

當(dāng)然上述只是一個(gè)非常簡(jiǎn)單的??,大家在編碼過程中只需要主要點(diǎn),如有涉及類似場(chǎng)景,請(qǐng)用這種方式去編碼,體驗(yàn)更愉悅!

六、總結(jié)

策略設(shè)計(jì)模式讓各種算法的代碼、內(nèi)部數(shù)據(jù)和依賴關(guān)系與其他代碼隔離開來。不同客戶端可通過一個(gè)簡(jiǎn)單接口執(zhí)行算法,并能在運(yùn)行時(shí)進(jìn)行切換。 

當(dāng)然在設(shè)計(jì)實(shí)現(xiàn)程序功能的時(shí)候,如果需要使用策略設(shè)計(jì)模式,也更需要我們的工程師有一個(gè)功能全局把控的能力,才能更好將依賴關(guān)系拆分,抽象化,以此才能凸顯“新生代”民工的不同!

責(zé)任編輯:武曉燕 來源: DYBOY
相關(guān)推薦

2021-08-19 15:27:47

新生代農(nóng)民工軟件信息技術(shù)

2021-08-18 07:37:02

程序員農(nóng)民工人力

2021-08-18 10:49:55

程序員新生代農(nóng)民工收入

2021-08-17 15:13:12

碼農(nóng)編程開發(fā)

2021-08-23 13:29:44

碼農(nóng)編程開發(fā)

2021-08-19 06:03:07

新生代農(nóng)民工數(shù)據(jù)分析碼農(nóng)

2021-08-23 14:59:58

技術(shù)資訊

2012-12-19 09:54:17

2010-04-15 17:52:58

微軟農(nóng)民工社區(qū)學(xué)習(xí)中心

2022-03-22 12:12:37

智能建造建筑機(jī)器人人工智能

2009-07-01 16:48:43

JAVA程序員

2009-04-13 09:37:42

IT新生代創(chuàng)業(yè)

2011-09-14 09:31:45

2012-11-27 15:06:50

IT面試

2022-04-29 08:00:51

V8垃圾回收

2009-11-16 15:55:19

博科資訊代理

2012-05-03 10:33:32

歐朋

2021-09-02 07:31:59

農(nóng)民工 996 國(guó)家

2022-03-22 13:58:33

人工智能建筑機(jī)器人農(nóng)民工
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)