1、策略模式定义:

将一系列算法封装起来,为了当前能够相互替换应用,由策略类和context组成,context承受用户信息,而后将申请委托给策略类
(现实生活中,咱们要去一个城市,交通形式就有:飞机、高铁、开车、大巴等,这些形式都能达到目的地,咱们能够依据本身需要来抉择一个策略)

2、策略模式的长处

1.策略模式利用组合、委托和多态等技术思维,能够无效的防止许多重条件抉择语句2.有弹性,恪守关闭/开发准则,将算法封装在独立的strategy中,使他易于切换、易于了解、易于扩大3.复用不便4.利用委托和组合来让context领有执行算法的能力,这也是继承的一种更轻便的代替计划

3、策略模式的毛病

1.会产生比拟多的类和函数2.要应用策略就要明确所有策略,违反常识起码化准则

4、通过策略模式学习播种到什么

1.封装变动、多态、委托

5、通过例子来加深策略模式的意识

1.奖金的计算
  <script>// ///////////////////////////////////没有应用策略模式/////////////////////////////////////////                function cuculateBounds(leave,salary){            if(leave==="A"){                return 4*salary            }else if(leave ==="B"){                return 3*salary            }else{                return 2*salary            }        }// console.log(cuculateBounds("A",3000))// console.log(cuculateBounds("B",3000))// 毛病:// 1、所有逻辑都在cuculateBounds函数体外面,要蕴含所有的if-else,体量宏大// 2、不足弹性,如果要批改奖金等级A的系数为3.5,就要扭转函数体,违反关闭凋谢与准则// 3、复用性差,如果要复用则要用复制粘贴// ///////////////////////////////////用策略模式改写/////////////////////////////////////////// 1. 将应用算法和算法离开,应用算法的形式不会变,算法会变,所以封装算法(封装变动)// 2.策略类-不同策略返回不同后果(多态)var strateies={    "A":function(salary){        return 4*salary;    },    "B":function(salary){        return 3*salary;    },    "C":function(salary){        return 2*salary;    }}// 3.context 应用算法,接管申请,不执行操作,将申请委托给策略类(委托)var caculateBounds = function(leave,salary){    return strateies[leave](salary);}console.log(caculateBounds("A",2000))
2.动画的实现
    <div id="box" style="position:absolute;width: 200px;height: 200px;background-color: cornflowerblue;"></div>    <script>        // /////////////////////1.策略类-封装动画缓动算法/////////////////////        /**params         *         *开始地位         *要挪动的间隔         *耗费了多少工夫         *总耗时         *  */        var easing={            "linear":function(starPos,pos,time,duration){                return pos*time/duration + starPos;            },            "easeIn":function( starPos,pos,time,duration){                return pos*(time/=duration)*time +starPos;            }        }        // /////////////////////2.动画类/////////////////////////////////        // 利用定时器,没19毫秒一帧,更新dom节点款式        function Animate(dom){            this.dom = dom ;        }        // 接管4个参数        /**         * 款式         * 挪动指标地位         * 执行工夫         * 缓动类型         * **/        Animate.prototype.start = function(propety,pos,duration,estype){            this.propety = propety;               // 开始地位            this.startPos = this.dom.getBoundingClientRect()[propety]            this.endPos = pos;            this.startTime = +new Date;            this.endTime = this.startTime+duration;            this.duraPos = pos-this.startPos;            this.easing = easing[estype];            this.duration = duration;            var _that = this;           var timeId =  setInterval(()=>{                if(_that.step()===false){                    // 清空定时器                    clearInterval(timeId)                    timeId = null;                }            },19)        }        Animate.prototype.step = function(){            // 以后工夫大于完结工夫,返回false            var nowTime =+new Date            if(nowTime>=this.endTime){                  // 校对地位                this.update(this.endPos)                return false            }else{               let pos =   this.easing(this.startPos,this.duraPos,nowTime-this.startTime,this.duration)                this.update(pos)            }        }        Animate.prototype.update =function(val){            this.dom.style[this.propety] = val+'px'        }        // /////////////////////////////3.调用动画////////////////        var dom  = document.getElementById("box");        var animate = new Animate(dom);        // animate.start("top",500,3000,"linear")        // animate.start("left",500,2000,"easeIn")        animate.start("left",500,2000,"linear")            </script>
3.验证表单
    <form id="formpane">        用户名:<input type="text" value="" id="userName" placeholder="请输出" />        手机号:<input type="tel" value="" id="telphoneNum" />        明码:<input type="password" value="" id="userPassword" />        <button type="submit">提交</button>    </form>    <script>        // 多规定验证,满足条件,表单放行        /**多规定验证,满足条件,表单放行         * 规定1:用户名不能为空         * 规定2:手机格局正确         * 规定3:明码长度小于6        */        let regisform = document.getElementById("formpane");        /////////////////////////没有策略模式写法(我的常见写法)//////////////////        // regisform.onsubmit = function(){        //     // 用户名不能为空        //     if(regisform.userName.value.length===0){        //         console.log("用户名不能为空")        //         return false        //     }        //     else if(!/(^1[3|5|8][0-9]{9}$)/.test(regisform.telphoneNum.value)){        //         console.log("手机格局不正确")        //         return false        //     }else if(regisform.userPassword.value.length>6){        //         // 明码长度小于6        //         console.log("明码长度小于6")        //         return false        //     }        //     alert("提交胜利")        // }        /**该写法的启发         * 1、表单的值能够通过表单的dom.id(子id)例regisform.userName         * 2、onsubmit函数体比拟宏大,蕴含所有的if-else逻辑         * 3、不足弹性,当要批改验证规定时,须要改变外部逻辑,违反关闭凋谢准则         * 4、不易复用         */        // ///////////////////////////用策略模式改写////////////////////        // 1、创立一个策略类        var stargeies = {            isNameEmpty: function (value, msg) {                if (value.length === 0)                    return msg            },            isNumberTrue: function (value, msg) {                if (!/(^1[3|5|8][0-9]{9}$)/.test(value)) {                    return msg                }            },            isMinlen: function (value, min, msg) {                if (value.length < min)                    return msg            }        }        // 2、创立一个context的类用来接管用户的申请        function Invalidator() {            this.catchs = [];        }        // 增加规定        Invalidator.prototype.add = function (dom, rules, msg) {            var arr = rules.split(":");            this.catchs.push(function () {                let starge = arr.shift();//删除数组第一个                let value = dom.value;                arr.unshift(value);//在数组第一个插入                arr.push(msg)                return stargeies[starge].apply(dom, arr);            })        }        // 执行规定返回后果        Invalidator.prototype.start = function () {            // 这种形式遍历,当满足条件,退出循环            for (let index = 0; index < this.catchs.length; index++) {                console.log(index);                let msg = this.catchs[index]();                if (msg) {                    return msg                }            }        }        // 3、用户调用规定,依据后果判断是否提交表单        // var invaliFunc = function(){        //     var invalidator = new Invalidator();        //     invalidator.add(regisform.userName,"isNameEmpty","用户名不能为空");        //     invalidator.add(regisform.telphoneNum,"isNumberTrue","手机格局不正确");        //     invalidator.add(regisform.userPassword,"isMinlen:8","明码长度不能小于8");        //    return invalidator.start();        // }        // regisform.onsubmit = function(){        // let value = invaliFunc()        // if(value){        //     console.log(value);        //     return false;        // }        // }        // //////////////////////////////策略模式-表单验证多规定//////////////        // 增加多规定        Invalidator.prototype.adds = function (dom, arrs) {            arrs.forEach(element => {                let { rules, msg } = element;                let arr = rules.split(":");                this.catchs.push(function () {                    let starge = arr.shift();//删除数组第一个                    let value = dom.value;                    arr.unshift(value);//在数组第一个插入                    arr.push(msg)                    return stargeies[starge].apply(dom, arr);                })            });        }        var invaliFunc = function () {            var invalidator = new Invalidator();            invalidator.adds(regisform.userName, [{ rules: "isNameEmpty", msg: "用户名不能为空" }, { rules: "isMinlen:6", msg: "用户名不能小于6" }]);            invalidator.add(regisform.telphoneNum, "isNumberTrue", "手机格局不正确");            invalidator.add(regisform.userPassword, "isMinlen:8", "明码长度不能小于8");            return invalidator.start();        }        regisform.onsubmit = function () {            let value = invaliFunc()            if (value) {                console.log(value);                return false;            }        }    </script>

6、理论场景中应用的高阶函数实现隐形的策略模式

    <!-- 常见的策略模式。不会有策略类来寄存策略办法 -->    <script>     function planA(params) {        console.log("A"+params)    }    function planB(params) {        console.log("B"+params)    }    function planC(params) {        console.log("C"+params)    }    // 应用高阶函数的形式,参数传入函数,而后将事件委托到策略类中执行,多态,调用这个办法传入不同状态,返回不同后果    function caculateBounds(func,params){        func(params)    }    caculateBounds(planA,"欢送应用A策略")    </script>