javaScript设计模式与开发实践(二)策略模式

 

策略模式定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。

 

使用策略模式计算奖金:

 

实现一:最初代码实现

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

 实现一缺点:

 函数庞大,if-else语句需要覆盖所有逻辑分支;

 函数缺乏弹性,新增绩效等级时,需要深入函数内部实现,违反了开放-封闭原则;

 算法复用性差。

 

实现二:策略模式,目的是将算法的使用与实现分离开

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

 通过使用策略模式重构代码,消除了原程序中大片的条件分支语句。

 策略对象负责的算法被各自封装在了对象内部。

 

使用策略模式验证表单:

 

实现一:普通方法

registerForm.onsubmit = function(){
if ( registerForm.userName.value === '' ){
  alert ( '用户名不能为空' );
  return false;
}
if ( registerForm.password.value.length < 6 ){
  alert ( '密码长度不能少于6 位' );
  return false;
}
if ( !/(^1[3|5|8][0-9]{9}$)/.test( registerForm.phoneNumber.value ) ){
  alert ( '手机号码格式不正确' );
  return false;
}
}

 实现一的缺点:

  onsubmit函数庞大,包含了很多If-else语句,需要覆盖所有校验规则

  onsubmit函数缺乏弹性

  算法复用性差,新增一个表单时,需要重新复制代码

 

实现二:策略模式

/***********************策略对象**************************/
var strategies = {

  isNonEmpty: function( value, errorMsg ){
    if ( value === '' ){
      return errorMsg;
    }
  },

  minLength: function( value, length, errorMsg ){
    if ( value.length < length ){
      return errorMsg;
    }
  },

  isMobile: function( value, errorMsg ){
    if ( !/(^1[3|5|8][0-9]{9}$)/.test( value ) ){
      return errorMsg;
    }
  }
};

/***********************Validator 类**************************/
var Validator = function() {
  this.cache = [];
};

Validator.prototype.add = function(dom, rules) {
var self = this;
for(var i=0,len=rules.length; i<len; i++) {
var rule = rules[i];
(function(rule){
var strategAry = rule.stratege.split(':'); var errorMsg = rule.errorMsg;
self.cache.push(function(){ var stratege = strategyAry.shift(); strategyAry.unshift( dom.value ); strategyAry.push( errorMsg ); return strategies[ strategy ].apply( dom, strategyAry ); }); })(rule); } }; Validator.prototype.start = function(){ for ( var i = 0, validatorFunc; validatorFunc = this.cache[ i++ ]; ){ var errorMsg = validatorFunc(); if ( errorMsg ){ return errorMsg; } } }; /***********************客户调用代码**************************/ var registerForm = document.getElementById( 'registerForm' ); var validataFunc = function(){ var validator = new Validator(); validator.add( registerForm.userName, [{ strategy: 'isNonEmpty', errorMsg: '用户名不能为空' }, { strategy: 'minLength:6', errorMsg: '用户名长度不能小于10 位' }]); validator.add( registerForm.password, [{ strategy: 'minLength:6', errorMsg: '密码长度不能小于6 位' }]); validator.add( registerForm.phoneNumber, [{ strategy: 'isMobile', errorMsg: '手机号码格式不正确' }]); var errorMsg = validator.start(); return errorMsg; } registerForm.onsubmit = function(){ var errorMsg = validataFunc(); if ( errorMsg ){ alert ( errorMsg ); return false; } };

 

策略模式的优缺点:

  优点:

  策略模式利用组合、委托和多态等技术和思想,可以有效地避免多重条件选择语句。
  策略模式提供了对开放—封闭原则的完美支持,将算法封装在独立的strategy 中,使得它们易于切换,易于理解,易于扩展。
  策略模式中的算法也可以复用在系统的其他地方,从而避免许多重复的复制粘贴工作。
  在策略模式中利用组合和委托来让Context 拥有执行算法的能力,这也是继承的一种更轻便的替代方案。

  缺点:

  使用策略模式会在程序中增加许多策略类或者策略对象。
  要使用策略模式,必须了解所有的strategy。

 

posted @ 2017-02-23 11:00  dreamerjdw  阅读(186)  评论(0编辑  收藏  举报