策略模式

策略模式就是将一系列算法封装起来,并使它们相互之间能够替换。被封装起来的算法具备独立性,内部不可扭转其个性。简略了解就是把 if 分支用函数封装成一个个代码块,对办法进行形象,便于后续代码的保护,体高代码复用率,较少代码冗余,毛病就是对于其余没有参加封装的其余开发者来说,他们并不知道有哪些办法能够应用,如果不去浏览这些算法,很容易走回以前的老套路或者反复封装,毛病就是不够直观易懂

对于前端来说策略模式实现的两个步骤

  • 实现形象的办法

把 if else 不必分支解决的事件形象成一个个不同、独立办法

  • 实现对外的接口

提供给内部调用的一个接口,依据内部给的不同的条件,进行不同的逻辑解决,找到对应的形象的办法

表单验证例子

开发一个用户注册页面,其中表单蕴含了用户名、明码、确认明码以及手机号码,要求所有数据都不为空,明码至多6位,确认明码必须与明码相等。

筹备工作,先把html和css写好

<style>.flex {    display: flex;    justify-content: space-between;    width: 300px;    margin: 10px;}</style><form action="" id="form">    <div class="flex">姓名:<input type="text" id="username" /></div>    <div class="flex">明码:<input type="password" id="password1" /></div>    <div class="flex">确认明码:<input type="password" id="password2" /></div>    <div class="flex">手机号:<input type="text" id="phone" /></div>    <div class="flex"><input type="submit" value="提交" /></div></form>

间接做表单验证:

var formData = document.getElementById('form')formData.onsubmit = function () {    var name = this.username.value    var pwd1 = this.password1.value    var pwd2 = this.password2.value    var tel = this.phone.value    if (name.replace(/(^\s*)|(\s*$)/g, '') === '') {        alert('用户名不能为空')        return false    }    if (pwd1.replace(/(^\s*)|(\s*$)/g, '') === '') {        alert('明码不能为空')        return false    }    if (pwd2.replace(/(^\s*)|(\s*$)/g, '') === '') {        alert('确认明码不能为空')        return false    }    if (pwd2 !== pwd1) {        alert('确认明码与原明码不雷同!')        return false    }    if (tel.replace(/(^\s*)|(\s*$)/g, '') === '') {        alert('手机号码不能为空')        return false    }    if (!/^1[3,4,5,7,8,9][0-9]\d{8}$/.test(tel)) {        alert('手机号码格局不正确')        return false    }    alert('注册胜利')}

间接做表单验证整个逻辑对于老手来说会很直观,没那么多弯弯绕绕的,然而毛病也显著,4个表单数据,就用了6个if去判断,如果这个页面不是用户注册,而是某个治理页面中的表单,蕴含了十多个表单数据呢,那只会更多。须要验证的越多,代码就会越来越臃肿,当须要进行很多验证的时候,能够思考策略模式

第一步,把 if else 不必分支解决的事件形象成一个个不同、独立办法

function Validate() {} // 定义在原型链,不便调用Validate.prototype.rules = {    // 是否手机号    isMobile: function (str) {        var rule = /^1[3,4,5,7,8,9][0-9]\d{8}$/        return rule.test(str)    },    // 是否必填    isRequired: function (str) {        // 除去首尾空格        var value = str.replace(/(^\s*)|(\s*$)/g, '')        return value !== ''    },    // 最小长度    minLength: function (str, length) {        var strLength = str.length        return strLength >= length    },    // 是否相等    isEqual: function () {        // 能够接管多个参数比拟        var args = Array.prototype.slice.call(arguments)        // 取首项与前面所有的项比拟,如果每个都相等,就返回true        var equal = args.every(function (value) {            return value === args[0]        })        return equal    }}

第二步,实现一个对外裸露的接口,或者说办法,供内部调用

Validate.prototype.test = function (rules) {    var v = this    var valid // 保留校验后果    for (var key in rules) {        // 遍历校验规定对象        for (var i = 0; i < rules[key].length; i++) {            // 遍历每一个字段的校验规定            var ruleName = rules[key][i].rule // 获取每一个校验规定的规定名            var value = rules[key][i].value // 获取每一个校验规定的校验值            if (!Array.isArray(value)) {                // 对立校验值为数组类型                value = new Array(value)            }            var result = v.rules[ruleName].apply(this, value) // 调用校验规定办法进行校验            if (!result) {                // 如果校验不通过,就获取校验后果信息,并立刻跳出循环不再执行,节约耗费                valid = {                    errValue: key,                    errMsg: rules[key][i].message                }                break            }        }        if (valid) {            // 如果有了校验后果,代表存在不通过的字段,则立刻进行循环,节约耗费            break        }    }    return valid // 把校验后果返回进来}

这个时候外部环境就能够调用了,外部环境要晓得调用的格局,就是说要晓得怎么用

var formData = document.getElementById('form')    formData.onsubmit = function () {        event.preventDefault() //阻止元素默认行为        console.log(this.username.value)        var validator = new Validate()        var result = validator.test({            username: [                {                    rule: 'isRequired',                    value: this.username.value,                    message: '用户名不能为空!'                }            ],            password1: [                {                    rule: 'isRequired',                    value: this.password1.value,                    message: '明码不能为空!'                },                {                    rule: 'minLength',                    value: [this.password1.value, 6],                    message: '明码长度不能小于6个字符!'                }            ],            password2: [                {                    rule: 'isRequired',                    value: this.password2.value,                    message: '确认明码不能为空!'                },                {                    rule: 'minLength',                    value: [this.password2.value, 6],                    message: '确认明码长度不能小于6个字符!'                },                {                    rule: 'isEqual',                    value: [this.password2.value, this.password1.value],                    message: '确认明码与原明码不雷同!'                }            ],            isMobile: [                {                    rule: 'isRequired',                    value: this.phone.value,                    message: '手机号不能为空!'                },                { rule: 'isMobile', value: this.phone.value, message: '手机号格局不正确!' }            ]        })        if (result) {            console.log(result)        } else {            console.log('校验通过')        }    }

参考:[https://zhuanlan.zhihu.com/p/...]