计策者方式,那么一般的写法是如此的

上一章大家介绍了单例格局及JavaScript惰性单例形式采取
那二遍作者主要介绍政策格局
安插形式是概念一文山会海的算法,把它们多个个包裹起来,并且让她们得以互相替换。
举个例子说在切实可行中繁多时候也有那个渠道到达同2个目标地,比方我们去有些地点出行,能够选取坐飞机,乘火车,骑自行车等措施。

 最终上一张全部代码

  

 1 // 策略对象
 2 var strategys = {
 3     isNotEmpty: function(value,errorMsg) {
 4         if(value === '') {
 5             return errorMsg;
 6         }
 7     },
 8     // 限制最小长度
 9     minLength: function(value,length,errorMsg) {
10         if(value.length < length) {
11             return errorMsg;
12         }
13     },
14     // 手机号码格式
15     mobileFormat: function(value,errorMsg) {
16         if(!/(^1[3|5|8][0-9]{9}$)/.test(value)) {
17             return errorMsg;
18         }
19     } 
20 };
21 var Validator = function(){
22     this.cache = [];  // 保存效验规则
23 };
24 Validator.prototype.add = function(dom,rules) {
25     var self = this;
26     for(var i = 0, rule; rule = rules[i++]; ){
27         (function(rule){
28             var strategyAry = rule.strategy.split(":");
29             var errorMsg = rule.errorMsg;
30             self.cache.push(function(){
31                 var strategy = strategyAry.shift();
32                 strategyAry.unshift(dom.value);
33                 strategyAry.push(errorMsg);
34                 return strategys[strategy].apply(dom,strategyAry);
35             });
36         })(rule);
37     }
38 };
39 Validator.prototype.start = function(){
40     for(var i = 0, validatorFunc; validatorFunc = this.cache[i++]; ) {
41     var msg = validatorFunc(); // 开始效验 并取得效验后的返回信息
42     if(msg) {
43         return msg;
44     }
45     }
46 };
47 // 代码调用
48 var registerForm = document.getElementById("registerForm");
49 var validateFunc = function(){
50     var validator = new Validator(); // 创建一个Validator对象
51     /* 添加一些效验规则 */
52     validator.add(registerForm.userName,[
53         {strategy: 'isNotEmpty',errorMsg:'用户名不能为空'},
54         {strategy: 'minLength:6',errorMsg:'用户名长度不能小于6位'}
55     ]);
56     validator.add(registerForm.password,[
57         {strategy: 'minLength:6',errorMsg:'密码长度不能小于6位'},
58     ]);
59     validator.add(registerForm.phoneNumber,[
60         {strategy: 'mobileFormat',errorMsg:'手机号格式不正确'},
61     ]);
62     var errorMsg = validator.start(); // 获得效验结果
63     return errorMsg; // 返回效验结果
64 };
65 // 点击确定提交
66 registerForm.onsubmit = function(){
67     var errorMsg = validateFunc();
68     if(errorMsg){
69         alert(errorMsg);
70         return false;
71     }
72 }

用政策格局重构表单校验

先是步大家要把这几个校验逻辑封装成计谋对象,也正是计谋类:

var strategies = {
 isNonEmpty: function  (value ,errorMsg) {
    if(value == '') return errorMsg
 },
 minLength: function  (value,length,errorMsg) {
    if(value.length < length) return errorMsg
 },
inMobile: function  (value,errorMsg) {
    if(!/(^1[3][5][8][0-9]{9}$)/.test(value)) return errorMsg 
}
};

ok ,今后大家先导写内容类。Validator 类在那里作为context
,担负接收用户的乞请,并委托给strategy对象。

var Validator = function  () {
this.cache = [];   // save the check format
}  
Validator.prototype.add = function  (dom,rule,errorMsg) {
var ary = rule.split(':')      // forExample : 'minLength:10'        
this.cache.push(function  () {
    var strategy = ary.shift() //  minLength
    ary.unshift(dom.value)     // forExample : registerForm.username
    ary.push(errorMsg);        //  ary= [registerForm.username,10]
    return strategies[strategy].apply(dom,ary)    //bring the dom & ary into strategies props.


});
};
Validator.prototype.start = function  () {
for (var i = 0; ValidatorFunc; ValidatorFunc = this.cache[i++]) {
     var msg = ValidatorFunc();
     if(msg) return msg;  // if have return value then the check is failed.
};
}

公海赌船,假若大家并未有写什么用户怎样向Validator类发送请求,上边清楚起来只怕相比较复杂。今后大家具体到表单看看。

var ValidatorFunc = function  () {
var validator = new Validator()
/***************add some format by the prototype     fun.*************************/
   validator.add(registerForm.username,'isNonEmpty','username cannot be     none');
   validator.add(registerForm.password,'minLength:6','password cannot be none');
   validator.add(registerForm.phoneNumber,'isMoblie','phoneNumber cannot be none');


   var errorMsg = Validator.start() // get the check result 
   return errorMsg                  // return the result. if exsit ...
}

  var registerForm = document.getElementById('registerForm')
  registerForm.onsubmit = function  () {
var errorMsg = validatorFunc()   // this is a instance!!!
if(errorMsg) 
    alert(errorMsg)
return false
}

这么大家大要造成了三个表单的布署方式重构(如若你能即时立时看懂的话…)

值得一提的是大家明天得以万分轻便轻松的修改校验规则,举个例子

validator.add(registerForm.username,'minLength:10','username cannot less than 10')  

 二. 宗旨格局的选择

  使用政策形式总括奖金 

  公司的年终奖是依附职员和工人的报酬和绩效来考核的,绩效为A的人,年底奖为薪资的4倍,绩效为B的人,年底奖为薪俸的3倍,绩效为C的人,年初奖为薪酬的2倍;现在大家选拔相似的编码方式会如下那样编写代码:

  公海赌船 1

   缺点如下: 

  
A) calculateBouns 函数包括了众多if else

 
  B) calcualteBouns 函数缺少弹性 要是还有D品级那么大家还必要在calculateBouns函数中增添企图等第D的if语句

  
C) 算法复用性差 假诺在另各省方也有类似那样的算法 可是规则区别等
这么大家的代码不能够通用。

  计谋形式

  公海赌船 2

在意我们的宗旨绪想就是要写七个类: 三个宗旨类 2个内容类

 3. 表单验证

  我们平日要实行表单验证
比方注册登陆对话框 大家登陆从前要开展表明操作举个例子:

  A) 用户名无法为空

  B) 密码长度无法小于陆

  C) 手提式有线电话机号码不可能不符合格式

  公海赌船 3

  小编从前的写法

  公海赌船 4  

  可是那样编写代码有如下缺点:

  1. registerForm.onsubmit 函数相当的大,代码中富含了成都百货上千if语句;
  2. registerForm.onsubmit 函数缺少弹性,借使增添了1种新的效用规则,恐怕想把密码的长短效验从6改成8,大家必须改registerForm.onsubmit 函数内部的代码。违背了开放-封闭原则
  3. 算法的复用性差,假诺在先后中追加了此外3个表单,这几个表单也急需张开一些看似的效益,那么大家也许又须求复制代码了;

    战略情势来重构表单校验。

  第三步封装战略对象

    公海赌船 5

  第1步: 计划完结Validator类,Validator类在此处作为Context,负担接收用户的伸手并委托给strategy 对象

  公海赌船 6   

  Validator类在此处当做Context,担负接收用户的请求并嘱托给strategys对象。上边的代码中,大家先创建3个Validator对象,然后经过validator.add方法往validator对象中加多一些效果规则,validator.add方法接收3个参数,如下代码:

validator.add(registerForm.password,’minLength:陆′,’密码长度不可能小于八人’);

  registerForm.password 为意义的input输入框dom节点;

  minLength:陆: 是以贰个冒号隔开分离的字符串,冒号前边的minLength代表客户选用的strategys对象,冒号前面的数字6意味在职能进度中所必须注明的参数,minLength:六的意思是作用 registerForm.password 这么些文件输入框的value最小长度为伍个人;借使字符串中不包罗冒号,表明效益进程中不供给格外的效用音讯;

  第二个参数是当效验未经过时回来的错误新闻;

  

  当大家往validator对象里增加完壹多样的法力规则之后,会调用validator.start()方法来运转作用。尽管validator.start()重临了贰个errorMsg字符串作为重回值,表达该次效验未有经过,此时亟需registerForm.onsubmit方法重回false来阻止表单提交.

  公海赌船 7

  假使大家既要效验输入框是还是不是为空,还要效验输入框的尺寸不要小于1二人的话,那么大家期望要求像如下传递参数:

   公海赌船 8

小结

宗旨格局是一种常用且使得的设计格局,大家能够计算出政策情势的1部分独到之处。

  1. 实用防止多种原则选取语句
  2. 全面接济了支付–封闭原则
  3. 轻便复用

 一. 计策情势定义和优点 

  计策者方式: 定义一文山会海的算法
把它们两个个包装起来 并使她们得以彼此替换。优点:

     A) 计谋格局选拔组合 委托等合计
有效幸免过多if条件语句。
     B) 战术格局提供了开荒——封闭原则
使代码更易于通晓和扩大。
     C)
攻略方式中的代码能够复用。

表单验证

校验表单音信或许都是稀松经常的作业,若是大家正在编写制定两个报了名的页面,在点击注册开关之前,有如下几条校验逻辑。

一.用户名不能够为空
二.密码长度不少于伍人
三.手提式有线电话机号码不能够不符合格式

假设大家今日从未引入政策情势,那么普通的写法是那般的:

<body>
 <form action='xxx' id='registerForm' method='post'>
      please entry username : <input type='text' name='username' />
      please entry password : <input type='text' name='password' />
      please entry phoneNumber : <input type='text' name='phoneNumber' />
             <button>submit</button>
 </form>
 <script>
     var registerForm = document.getElementById('registerForm')
     registerForm.onsubmit = function  () {
        if(registerForm.username.value == ''){
             alert('username cannot be none')
             return false;
        }
        if(registerForm.password.value.length < 6 ){
             alert('password length cannot less than 6')
             return false;
        }
        if(!/(^1[3][5][8][0-9]{9}$)/.test(registerForm.phoneNumber.value)){
            alert('phoneNumber format error')
            return false;
        }
     }
 </script>
</body>

综上可得那种面向进程的艺术繁琐且不复用贫乏弹性,简单的讲,大家亟须用政策格局重构之。

行使政策情势总结奖金

众多供销合作社的年初奖是依据员工的工薪基数和年终绩效来发放的。比如,绩效为 S
的人年底奖有四倍薪给,绩效为 A 的人年初奖有三倍薪给,绩效为 B
的人年初奖有二倍报酬。
未来我们来计量职员和工人的岁末奖。

  var performanceS = function  (salary) {
return salary * 4;
}
var performanceA = function  (salary) {
return salary * 3;
}
var performanceB = function  (salary) {
return salary * 2;
}
var calculateBonus = function  (performanceLevel,salary) {
if(performanceLevel === 'S')
    return performanceS(salary)
if(performanceLevel === 'A')
    return performanceA(salary)
if(performanceLevel === 'B')
    return performanceB(salary)

}
calculateBonus('A',10000);  // 30000

值得1提的是上述代码并不合乎政策形式定义
政策模式是概念一多元的算法,把它们3个个包装起来,并且让他俩能够互相替换。
那句话掌握起来正是概念一文山会海的算法,把它们各自封装成战略类,算法被封装在计策类内部的点子里。
从而大家必须做点改变

在JavaScript中,函数也是目的,所以我们能够直接将定义二个对象strategy用来存放在计策类。
参见代码:

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

以上基本吻合了计策形式的概念及写法。

更广义的算法

用政策情势仅仅来封装算法未免有志无时,在实际开垦中,也得以用政策情势来封装一些业务规则。
接下去我们用政策情势来形成表单验证的事例。

相关文章