成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

javascript設(shè)計(jì)模式之策略模式的示例

這篇文章給大家分享的是有關(guān)javascript設(shè)計(jì)模式之策略模式的示例的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。

成都創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),南山企業(yè)網(wǎng)站建設(shè),南山品牌網(wǎng)站建設(shè),網(wǎng)站定制,南山網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷(xiāo),網(wǎng)絡(luò)優(yōu)化,南山網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M(mǎn)足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專(zhuān)業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶(hù)成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

Java的優(yōu)點(diǎn)是什么

1. 簡(jiǎn)單,只需理解基本的概念,就可以編寫(xiě)適合于各種情況的應(yīng)用程序;2. 面向?qū)ο螅?. 分布性,Java是面向網(wǎng)絡(luò)的語(yǔ)言;4. 魯棒性,java提供自動(dòng)垃圾收集來(lái)進(jìn)行內(nèi)存管理,防止程序員在管理內(nèi)存時(shí)容易產(chǎn)生的錯(cuò)誤。;5. 安全性,用于網(wǎng)絡(luò)、分布環(huán)境下的Java必須防止病毒的入侵。6. 體系結(jié)構(gòu)中立,只要安裝了Java運(yùn)行時(shí)系統(tǒng),就可在任意處理器上運(yùn)行。7. 可移植性,Java可以方便地移植到網(wǎng)絡(luò)上的不同機(jī)器。8.解釋執(zhí)行,Java解釋器直接對(duì)Java字節(jié)碼進(jìn)行解釋執(zhí)行。

1. 理解javascript中的策略模式

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

使用策略模式的優(yōu)點(diǎn)如下:

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

      1. 策略模式利用組合,委托等技術(shù)和思想,有效的避免很多if條件語(yǔ)句。

      2. 策略模式提供了開(kāi)放-封閉原則,使代碼更容易理解和擴(kuò)展。

      3. 策略模式中的代碼可以復(fù)用。

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

下面的demo是我在書(shū)上看到的,但是沒(méi)有關(guān)系,我們只是來(lái)理解下策略模式的使用而已,我們可以使用策略模式來(lái)計(jì)算獎(jiǎng)金問(wèn)題;

比如公司的年終獎(jiǎng)是根據(jù)員工的工資和績(jī)效來(lái)考核的,績(jī)效為A的人,年終獎(jiǎng)為工資的4倍,績(jī)效為B的人,年終獎(jiǎng)為工資的3倍,績(jī)效為C的人,年終獎(jiǎng)為工資的2倍;現(xiàn)在我們使用一般的編碼方式會(huì)如下這樣編寫(xiě)代碼:

var calculateBouns = function(salary,level) {
  if(level === 'A') {
    return salary * 4;
  }
  if(level === 'B') {
    return salary * 3;
  }
  if(level === 'C') {
    return salary * 2;
  }
};
// 調(diào)用如下:
console.log(calculateBouns(4000,'A')); // 16000
console.log(calculateBouns(2500,'B')); // 7500

第一個(gè)參數(shù)為薪資,第二個(gè)參數(shù)為等級(jí);

代碼缺點(diǎn)如下:

calculateBouns 函數(shù)包含了很多if-else語(yǔ)句。

calculateBouns 函數(shù)缺乏彈性,假如還有D等級(jí)的話,那么我們需要在calculateBouns 函數(shù)內(nèi)添加判斷等級(jí)D的if語(yǔ)句;

算法復(fù)用性差,如果在其他的地方也有類(lèi)似這樣的算法的話,但是規(guī)則不一樣,我們這些代碼不能通用。

2. 使用組合函數(shù)重構(gòu)代碼

組合函數(shù)是把各種算法封裝到一個(gè)個(gè)的小函數(shù)里面,比如等級(jí)A的話,封裝一個(gè)小函數(shù),等級(jí)為B的話,也封裝一個(gè)小函數(shù),以此類(lèi)推;如下代碼:

var performanceA = function(salary) {
  return salary * 4;
};
var performanceB = function(salary) {
  return salary * 3;
};
    
var performanceC = function(salary) {
  return salary * 2
};
var calculateBouns = function(level,salary) {
  if(level === 'A') {
    return performanceA(salary);
  }
  if(level === 'B') {
    return performanceB(salary);
  }
  if(level === 'C') {
    return performanceC(salary);
  }
};
// 調(diào)用如下
console.log(calculateBouns('A',4500)); // 18000

代碼看起來(lái)有點(diǎn)改善,但是還是有如下缺點(diǎn):

calculateBouns 函數(shù)有可能會(huì)越來(lái)越大,比如增加D等級(jí)的時(shí)候,而且缺乏彈性。

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

策略模式指的是 定義一系列的算法,把它們一個(gè)個(gè)封裝起來(lái),將不變的部分和變化的部分隔開(kāi),實(shí)際就是將算法的使用和實(shí)現(xiàn)分離出來(lái);算法的使用方式是不變的,都是根據(jù)某個(gè)算法取得計(jì)算后的獎(jiǎng)金數(shù),而算法的實(shí)現(xiàn)是根據(jù)績(jī)效對(duì)應(yīng)不同的績(jī)效規(guī)則;

一個(gè)基于策略模式的程序至少由2部分組成,第一個(gè)部分是一組策略類(lèi),策略類(lèi)封裝了具體的算法,并負(fù)責(zé)具體的計(jì)算過(guò)程。第二個(gè)部分是環(huán)境類(lèi)Context,該Context接收客戶(hù)端的請(qǐng)求,隨后把請(qǐng)求委托給某一個(gè)策略類(lèi)。我們先使用傳統(tǒng)面向?qū)ο髞?lái)實(shí)現(xiàn);

如下代碼:

var performanceA = function(){};
performanceA.prototype.calculate = function(salary) {
  return salary * 4;
};   
var performanceB = function(){};
performanceB.prototype.calculate = function(salary) {
  return salary * 3;
};
var performanceC = function(){};
performanceC.prototype.calculate = function(salary) {
  return salary * 2;
};
// 獎(jiǎng)金類(lèi)
var Bouns = function(){
  this.salary = null;  // 原始工資
  this.levelObj = null; // 績(jī)效等級(jí)對(duì)應(yīng)的策略對(duì)象
};
Bouns.prototype.setSalary = function(salary) {
  this.salary = salary; // 保存員工的原始工資
};
Bouns.prototype.setlevelObj = function(levelObj){
  this.levelObj = levelObj; // 設(shè)置員工績(jī)效等級(jí)對(duì)應(yīng)的策略對(duì)象
};
// 取得獎(jiǎng)金數(shù)
Bouns.prototype.getBouns = function(){
  // 把計(jì)算獎(jiǎng)金的操作委托給對(duì)應(yīng)的策略對(duì)象
  return this.levelObj.calculate(this.salary);
};
var bouns = new Bouns();
bouns.setSalary(10000);
bouns.setlevelObj(new performanceA()); // 設(shè)置策略對(duì)象
console.log(bouns.getBouns()); // 40000
    
bouns.setlevelObj(new performanceB()); // 設(shè)置策略對(duì)象
console.log(bouns.getBouns()); // 30000

如上代碼使用策略模式重構(gòu)代碼,可以看到代碼職責(zé)更新分明,代碼變得更加清晰。

4. Javascript版本的策略模式

//代碼如下:
var obj = {
    "A": function(salary) {
      return salary * 4;
    },
    "B" : function(salary) {
      return salary * 3;
    },
    "C" : function(salary) {
      return salary * 2;
    } 
};
var calculateBouns =function(level,salary) {
  return obj[level](salary);
};
console.log(calculateBouns('A',10000)); // 40000

可以看到代碼更加簡(jiǎn)單明了;

策略模式指的是定義一系列的算法,并且把它們封裝起來(lái),但是策略模式不僅僅只封裝算法,我們還可以對(duì)用來(lái)封裝一系列的業(yè)務(wù)規(guī)則,只要這些業(yè)務(wù)規(guī)則目標(biāo)一致,我們就可以使用策略模式來(lái)封裝它們;

表單效驗(yàn)

比如我們經(jīng)常來(lái)進(jìn)行表單驗(yàn)證,比如注冊(cè)登錄對(duì)話框,我們登錄之前要進(jìn)行驗(yàn)證操作:比如有以下幾條邏輯:

用戶(hù)名不能為空

密碼長(zhǎng)度不能小于6位。

手機(jī)號(hào)碼必須符合格式。

比如HTML代碼如下:

<form action = "http://www.baidu.com" id="registerForm" method = "post">
    <p>
      <label>請(qǐng)輸入用戶(hù)名:</label>
      <input type="text" name="userName"/>
    </p>
    <p>
      <label>請(qǐng)輸入密碼:</label>
      <input type="text" name="password"/>
    </p>
    <p>
      <label>請(qǐng)輸入手機(jī)號(hào)碼:</label>
      <input type="text" name="phoneNumber"/>
    </p>
</form>

我們正常的編寫(xiě)表單驗(yàn)證代碼如下:

var registerForm = document.getElementById("registerForm");
registerForm.onsubmit = function(){
  if(registerForm.userName.value === '') {
    alert('用戶(hù)名不能為空');
    return;
  }
  if(registerForm.password.value.length < 6) {
    alert("密碼的長(zhǎng)度不能小于6位");
    return;
  }
  if(!/(^1[3|5|8][0-9]{9}$)/.test(registerForm.phoneNumber.value)) {
    alert("手機(jī)號(hào)碼格式不正確");
    return;
  }
}


但是這樣編寫(xiě)代碼有如下缺點(diǎn):

1.registerForm.onsubmit 函數(shù)比較大,代碼中包含了很多if語(yǔ)句;

2.registerForm.onsubmit 函數(shù)缺乏彈性,如果增加了一種新的效驗(yàn)規(guī)則,或者想把密碼的長(zhǎng)度效驗(yàn)從6改成8,我們必須改registerForm.onsubmit 函數(shù)內(nèi)部的代碼。違反了開(kāi)放-封閉原則。

3. 算法的復(fù)用性差,如果在程序中增加了另外一個(gè)表單,這個(gè)表單也需要進(jìn)行一些類(lèi)似的效驗(yàn),那么我們可能又需要復(fù)制代碼了;

下面我們可以使用策略模式來(lái)重構(gòu)表單效驗(yàn);

第一步我們先來(lái)封裝策略對(duì)象;如下代碼:

var strategy = {
  isNotEmpty: function(value,errorMsg) {
    if(value === '') {
      return errorMsg;
    }
  },
  // 限制最小長(zhǎng)度
  minLength: function(value,length,errorMsg) {
    if(value.length < length) {
      return errorMsg;
    }
  },
  // 手機(jī)號(hào)碼格式
  mobileFormat: function(value,errorMsg) {
    if(!/(^1[3|5|8][0-9]{9}$)/.test(value)) {
      return errorMsg;
    }
  } 
};

接下來(lái)我們準(zhǔn)備實(shí)現(xiàn)Validator類(lèi),Validator類(lèi)在這里作為Context,負(fù)責(zé)接收用戶(hù)的請(qǐng)求并委托給strategy 對(duì)象,如下代碼:

var Validator = function(){
  this.cache = []; // 保存效驗(yàn)規(guī)則
};
Validator.prototype.add = function(dom,rule,errorMsg) {
  var str = rule.split(":");
  this.cache.push(function(){
    // str 返回的是 minLength:6 
    var strategy = str.shift();
    str.unshift(dom.value); // 把input的value添加進(jìn)參數(shù)列表
    str.push(errorMsg); // 把errorMsg添加進(jìn)參數(shù)列表
    return strategys[strategy].apply(dom,str);
  });
};
Validator.prototype.start = function(){
  for(var i = 0, validatorFunc; validatorFunc = this.cache[i++]; ) {
    var msg = validatorFunc(); // 開(kāi)始效驗(yàn) 并取得效驗(yàn)后的返回信息
    if(msg) {
      return msg;
    }
  }
};

Validator類(lèi)在這里作為Context,負(fù)責(zé)接收用戶(hù)的請(qǐng)求并委托給strategys對(duì)象。上面的代碼中,我們先創(chuàng)建一個(gè)Validator對(duì)象,然后通過(guò)validator.add方法往validator對(duì)象中添加一些效驗(yàn)規(guī)則,validator.add方法接收3個(gè)參數(shù),如下代碼:

validator.add(registerForm.password,'minLength:6','密碼長(zhǎng)度不能小于6位');

registerForm.password 為效驗(yàn)的input輸入框dom節(jié)點(diǎn);

minLength:6: 是以一個(gè)冒號(hào)隔開(kāi)的字符串,冒號(hào)前面的minLength代表客戶(hù)挑選的strategys對(duì)象,冒號(hào)后面的數(shù)字6表示在效驗(yàn)過(guò)程中所必須驗(yàn)證的參數(shù),minLength:6的意思是效驗(yàn) registerForm.password 這個(gè)文本輸入框的value最小長(zhǎng)度為6位;如果字符串中不包含冒號(hào),說(shuō)明效驗(yàn)過(guò)程中不需要額外的效驗(yàn)信息;

第三個(gè)參數(shù)是當(dāng)效驗(yàn)未通過(guò)時(shí)返回的錯(cuò)誤信息;

當(dāng)我們往validator對(duì)象里添加完一系列的效驗(yàn)規(guī)則之后,會(huì)調(diào)用validator.start()方法來(lái)啟動(dòng)效驗(yàn)。如果validator.start()返回了一個(gè)errorMsg字符串作為返回值,說(shuō)明該次效驗(yàn)沒(méi)有通過(guò),此時(shí)需要registerForm.onsubmit方法返回false來(lái)阻止表單提交。下面我們來(lái)看看初始化代碼如下:

var validateFunc = function(){
  var validator = new Validator(); // 創(chuàng)建一個(gè)Validator對(duì)象
  /* 添加一些效驗(yàn)規(guī)則 */
  validator.add(registerForm.userName,'isNotEmpty','用戶(hù)名不能為空');
  validator.add(registerForm.password,'minLength:6','密碼長(zhǎng)度不能小于6位');
  validator.add(registerForm.userName,'mobileFormat','手機(jī)號(hào)碼格式不正確');

  var errorMsg = validator.start(); // 獲得效驗(yàn)結(jié)果
  return errorMsg; // 返回效驗(yàn)結(jié)果
};
var registerForm = document.getElementById("registerForm");
registerForm.onsubmit = function(){
  var errorMsg = validateFunc();
  if(errorMsg){
    alert(errorMsg);
    return false;
  }
}

下面是所有的代碼如下:

var strategys = {
  isNotEmpty: function(value,errorMsg) {
    if(value === '') {
      return errorMsg;
    }
  },
  // 限制最小長(zhǎng)度
  minLength: function(value,length,errorMsg) {
    if(value.length < length) {
      return errorMsg;
    }
  },
  // 手機(jī)號(hào)碼格式
  mobileFormat: function(value,errorMsg) {
    if(!/(^1[3|5|8][0-9]{9}$)/.test(value)) {
      return errorMsg;
    }
  } 
};
var Validator = function(){
  this.cache = []; // 保存效驗(yàn)規(guī)則
};
Validator.prototype.add = function(dom,rule,errorMsg) {
  var str = rule.split(":");
  this.cache.push(function(){
    // str 返回的是 minLength:6 
    var strategy = str.shift();
    str.unshift(dom.value); // 把input的value添加進(jìn)參數(shù)列表
    str.push(errorMsg); // 把errorMsg添加進(jìn)參數(shù)列表
    return strategys[strategy].apply(dom,str);
  });
};
Validator.prototype.start = function(){
  for(var i = 0, validatorFunc; validatorFunc = this.cache[i++]; ) {
    var msg = validatorFunc(); // 開(kāi)始效驗(yàn) 并取得效驗(yàn)后的返回信息
    if(msg) {
      return msg;
    }
  }
};

var validateFunc = function(){
  var validator = new Validator(); // 創(chuàng)建一個(gè)Validator對(duì)象
  /* 添加一些效驗(yàn)規(guī)則 */
  validator.add(registerForm.userName,'isNotEmpty','用戶(hù)名不能為空');
  validator.add(registerForm.password,'minLength:6','密碼長(zhǎng)度不能小于6位');
  validator.add(registerForm.userName,'mobileFormat','手機(jī)號(hào)碼格式不正確');

  var errorMsg = validator.start(); // 獲得效驗(yàn)結(jié)果
  return errorMsg; // 返回效驗(yàn)結(jié)果
};
var registerForm = document.getElementById("registerForm");
registerForm.onsubmit = function(){
  var errorMsg = validateFunc();
  if(errorMsg){
    alert(errorMsg);
    return false;
  }
};

如上使用策略模式來(lái)編寫(xiě)表單驗(yàn)證代碼可以看到好處了,我們通過(guò)add配置的方式就完成了一個(gè)表單的效驗(yàn);這樣的話,那么代碼可以當(dāng)做一個(gè)組件來(lái)使用,并且可以隨時(shí)調(diào)用,在修改表單驗(yàn)證規(guī)則的時(shí)候,也非常方便,通過(guò)傳遞參數(shù)即可調(diào)用;

給某個(gè)文本輸入框添加多種效驗(yàn)規(guī)則,上面的代碼我們可以看到,我們只是給輸入框只能對(duì)應(yīng)一種效驗(yàn)規(guī)則,比如上面的我們只能效驗(yàn)輸入框是否為空,validator.add(registerForm.userName,'isNotEmpty','用戶(hù)名不能為空');但是如果我們既要效驗(yàn)輸入框是否為空,還要效驗(yàn)輸入框的長(zhǎng)度不要小于10位的話,那么我們期望需要像如下傳遞參數(shù):

validator.add(registerForm.userName,[{strategy:'isNotEmpty',errorMsg:'用戶(hù)名不能為空'},{strategy: 'minLength:6',errorMsg:'用戶(hù)名長(zhǎng)度不能小于6位'}])

我們可以編寫(xiě)代碼如下:

// 策略對(duì)象
var strategys = {
  isNotEmpty: function(value,errorMsg) {
    if(value === '') {
      return errorMsg;
    }
  },
  // 限制最小長(zhǎng)度
  minLength: function(value,length,errorMsg) {
    if(value.length < length) {
      return errorMsg;
    }
  },
  // 手機(jī)號(hào)碼格式
  mobileFormat: function(value,errorMsg) {
    if(!/(^1[3|5|8][0-9]{9}$)/.test(value)) {
      return errorMsg;
    }
  } 
};
var Validator = function(){
  this.cache = []; // 保存效驗(yàn)規(guī)則
};
Validator.prototype.add = function(dom,rules) {
  var self = this;
  for(var i = 0, rule; rule = rules[i++]; ){
    (function(rule){
      var strategyAry = rule.strategy.split(":");
      var errorMsg = rule.errorMsg;
      self.cache.push(function(){
        var strategy = strategyAry.shift();
        strategyAry.unshift(dom.value);
        strategyAry.push(errorMsg);
        return strategys[strategy].apply(dom,strategyAry);
      });
    })(rule);
  }
};
Validator.prototype.start = function(){
  for(var i = 0, validatorFunc; validatorFunc = this.cache[i++]; ) {
  var msg = validatorFunc(); // 開(kāi)始效驗(yàn) 并取得效驗(yàn)后的返回信息
  if(msg) {
    return msg;
  }
  }
};
// 代碼調(diào)用
var registerForm = document.getElementById("registerForm");
var validateFunc = function(){
  var validator = new Validator(); // 創(chuàng)建一個(gè)Validator對(duì)象
  /* 添加一些效驗(yàn)規(guī)則 */
  validator.add(registerForm.userName,[
    {strategy: 'isNotEmpty',errorMsg:'用戶(hù)名不能為空'},
    {strategy: 'minLength:6',errorMsg:'用戶(hù)名長(zhǎng)度不能小于6位'}
  ]);
  validator.add(registerForm.password,[
    {strategy: 'minLength:6',errorMsg:'密碼長(zhǎng)度不能小于6位'},
  ]);
  validator.add(registerForm.phoneNumber,[
    {strategy: 'mobileFormat',errorMsg:'手機(jī)號(hào)格式不正確'},
  ]);
  var errorMsg = validator.start(); // 獲得效驗(yàn)結(jié)果
  return errorMsg; // 返回效驗(yàn)結(jié)果
};
// 點(diǎn)擊確定提交
registerForm.onsubmit = function(){
  var errorMsg = validateFunc();
  if(errorMsg){
    alert(errorMsg);
    return false;
  }
}

注意:如上代碼都是按照書(shū)上來(lái)做的,都是看到書(shū)的代碼,最主要我們理解策略模式實(shí)現(xiàn),比如上面的表單驗(yàn)證功能是這樣封裝的代碼,我們平時(shí)使用jquery插件表單驗(yàn)證代碼原來(lái)是這樣封裝的,為此我們以后也可以使用這種方式來(lái)封裝表單等學(xué)習(xí);

感謝各位的閱讀!關(guān)于“javascript設(shè)計(jì)模式之策略模式的示例”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

標(biāo)題名稱(chēng):javascript設(shè)計(jì)模式之策略模式的示例
分享網(wǎng)址:http://jinyejixie.com/article32/igojpc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化、軟件開(kāi)發(fā)動(dòng)態(tài)網(wǎng)站、品牌網(wǎng)站制作、網(wǎng)站改版、商城網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

營(yíng)銷(xiāo)型網(wǎng)站建設(shè)
宜君县| 安龙县| 连州市| 宜州市| 修水县| 固始县| 三江| 达拉特旗| 万山特区| 静乐县| 句容市| 宜昌市| 仁化县| 周口市| 柳州市| 木兰县| 东丰县| 嘉定区| 台湾省| 桃江县| 宜阳县| 读书| 新化县| 大石桥市| 乌鲁木齐县| 阆中市| 新竹市| 阿克苏市| 宁乡县| 安塞县| 张家口市| 汉寿县| 荔浦县| 清新县| 开平市| 丰城市| 新田县| 吉水县| 金坛市| 海林市| 彰化县|