策略模式

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

一个基于策略模式的程序至少由两部分组成。第一个部分是一组策略类,策略类封装了具体 的算法,并负责具体的计算过程。 第二个部分是环境类 Context,Context接受客户的请求,随后 把请求委托给某一个策略类。要做到这点,说明 Context中要维持对某个策略对象的引用。

  • 用策略模式设计计算年终奖的案例
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 

使用策略模式的设计后,如果需要修改s评级的计算方法,可以使用strategies.s进行修改

策略模式的本质就是对同套流程的不同执行方法的选择,可以将不同的流程单独提出,写出策略类,可以在执行的时候,选择不同的策略;同时,策略内的方法可以方便的进行改写,不用深入代码内部进行删减修改。

多态在策略模式中的体现

通过使用策略模式重构代码,我们消除了原程序中大片的条件分支语句。所有跟计算奖金有 关的逻辑不再放在 Context中,而是分布在各个策略对象中。Context并没有计算奖金的能力,而 是把这个职责委托给了某个策略对象。每个策略对象负责的算法已被各自封装在对象内部。当我 们对这些策略对象发出“计算奖金”的请求时,它们会返回各自不同的计算结果,这正是对象多 态性的体现,也是“它们可以相互替换”的目的。替换 Context中当前保存的策略对象,便能执 行不同的算法来得到我们想要的结果。

用策略模式重构表单校验

<!DOCTYPE html>
<html>

<body>
    <form action="http:// xxx.com/register" id="registerForm" method="post">
        请输入用户名:<input type="text" name="userName" />
        请输入密码:<input type="text" name="password" />
        请输入手机号码:<input type="text" name="phoneNumber" />
        <button>提交</button>
    </form>
    <script>
        // 构建策略对象
        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;
                }
            }
        };
        
        /**
         * 客户调用代码
         **/
        var validataFunc = function () {
            var validator = new Validator();    // 创建一个 validator 对象 

            /***************添加一些校验规则****************/
            validator.add(registerForm.userName, 'isNonEmpty', '用户名不能为空');
            validator.add(registerForm.password, 'minLength:6', '密码长度不能少于 6 位');
            validator.add(registerForm.phoneNumber, 'isMobile', '手机号码格式不正确');

            var errorMsg = validator.start();    // 获得校验结果    
            return errorMsg;  // 返回校验结果 } 

            var registerForm = document.getElementById('registerForm');
            registerForm.onsubmit = function () {
                var errorMsg = validataFunc();   // 如果 errorMsg 有确切的返回值,说明未通过校验     
                if (errorMsg) {
                    alert(errorMsg);
                    return false;    // 阻止表单提交     
                }
            };
        }
        /**
         * Validator 类的实现
         **/
        var Validator = function () {
            this.cache = [];        // 保存校验规则 
        };

        Validator.prototype.add = function (dom, rule, errorMsg) {
            var ary = rule.split(':');    // 把 strategy 和参数分开   
            this.cache.push(function () {  // 把校验的步骤用空函数包装起来,并且放入 cache       
                var strategy = ary.shift();     // 用户挑选的 strategy       
                ary.unshift(dom.value);    // 把 input 的 value 添加进参数列表       
                ary.push(errorMsg);    // 把 errorMsg 添加进参数列表    
                return strategies[strategy].apply(dom, ary);
            });
        };

        Validator.prototype.start = function () {
            for (var i = 0, validatorFunc; validatorFunc = this.cache[i++];) {
                var msg = validatorFunc();    // 开始校验,并取得校验后的返回信息        
                if (msg) {     // 如果有确切的返回值,说明校验没有通过       
                    return msg;
                }
            }
        };

    </script>
</body>

</html>

在修改某个校验规则的时候,只需要编写或者改写少量的代码。比如我们想将用户名输入框 的校验规则改成用户名不能少于 4个字符。可以看到,这时候的修改是毫不费力的。

validator.add( registerForm.userName, 'isNonEmpty', '用户名不能为空' ); 
// 改成: 
validator.add( registerForm.userName, 'minLength:10', '用户名长度不能小于 10 位' ); 
  • 在 JavaScript语言的策略模式中,策略类往往被函数所代替,这时策略模式就 成为一种“隐形”的模式。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值