@(前端)[设计模式,JavaScript,TypeScript]javascript
策略模式解决的问题:策略模式要解决的问题是,代码的复用和扩展问题。若是没有策略模式的代码是将处理函数代码与逻辑代码混在一块儿写,这样写的好处是一次写好,但代码的扩展性与代码的复用性很差。html
没有用策略模式的例子代码:前端
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
能够看到的缺点是:若是想要扩充代码,只能在原来的对象上插入新的代码,对于代码的原做者来讲这不是为题,可是对于看别人写的代码的人来讲这样的代码想要作后期的维护难度之高可想而知。为了写出具备高复用性,好维护的,可扩展的代码来讲这样的代码风格是不合适的。java
1.分离出代码中“变”与“不变”的部分。其中“变”的部分是啥?应该是后续代码中要扩展的部分,不是将内容固定死的代码。而不变的部分就是代码调用部分,一般来讲代码中的调用部分是固定不变的。
2.因此将原本深度耦合的代码分离出来,我本身给取了名字叫条件代码和调用代码;条件代码时可变的可扩展的,一般放到外部的模块中用来调用和提升可维护性。而调用代码提供set
和`get
类方法用来设置条件代码的运行时须要的参数和调用调用代码用来输出结果。typescript
/* 定义各类计算方式 */ class L1{ calculate(base:number){ return base*2; } } class L2{ calculate(base:number){ return base*3; } } class L3 { calculate(base: number) { return base * 4; } }
/* 定义计算的调用方法类 */ class Calculate{ private base: number; private way: any; setBase(base: number) { this.base = base; } setLeve(leve:Object) { this.way = leve; } getResult(){ return this.way.calculate(this.base); } }
let calculater = new Calculate(); //实例化生成可调用对象 calculater.setBase(1000); //设置计算基础 calculater.setLeve( new L1() ); //设置计算的方式 console.log(calculater.getResult()); //get类方法,输出最后的结果
从以上代码可看出,扩展可在条件代码中扩展。保持了代码的高扩展和高可维护性。设计模式
html代码app
<body> <form action="#" method="post"> <span>用户名:</span><input type="text" name="user"> <span>密码:</span><input type="password" name="pwd"> <span>手机号码:</span><input id="ph" type="text" name="phoneNumber"> <input type="submit" value="提交"> </form> <script src="ms/m3.js"></script> </body>
typescript代码dom
/* 定义检查表单的规则 */ namespace RuleList{ export const Rules: any = { "isNotEmpty": function (value: any, errMsg: string) { console.log(11); if (value === '') return errMsg; }, "minLength": function (value: any, minLength: number, errMsg: string) { console.log(22); if (value.length < minLength) return errMsg; }, "isMobile": function (value: any, errMsg: string) { console.log(33); if (!/^1[3|5|8][0-9]{9}$/.test(value)) return errMsg; } } } /* 定义检查表单的方法类:add():添加检查的规则; start():开始检查 */ class Validator { cache: object[] = []; add(dom: any, rule: string, errMsg: string) { let arr: any = rule.split(':'); this.cache.push(function () { let whichRule: string = arr.shift(); arr.unshift(dom.value); arr.push(errMsg); return RuleList.Rules[whichRule].apply(dom, arr); }); }; start() { for (let i: number = 0, func: any; i < this.cache.length; i++) { func = this.cache[i]; let msg = func(); if (msg) return msg; //若是有返回值说明验证没有经过 } } } /* 策略模式的表单校验 */ let regForm = document.querySelector('form'); let usr:any = document.querySelector('input[type=text]:first-of-type'); let pwd:any = document.querySelector('input[type=password]'); let phone:any = document.querySelector('#ph'); /* 检查表单的函数 ->1.1 */ let ValidataFunc = function(){ let validator = new Validator(); validator.add(usr, 'isNotEmpty','用户名为空'); validator.add(pwd, 'isNotEmpty', '密码为空'); validator.add(pwd, 'minLength:6', '密码小于6位'); validator.add(phone,'isMobile','号码不是手机号码'); let msg = validator.start(); return msg; } /* 检查表单的函数 ->1. */ if( regForm ){ regForm.onsubmit = function(){ let errMsg = ValidataFunc(); if( errMsg ){ alert(errMsg); return false; } } }