常用js设计模式整理
在做canvas、webGL游戏时,很深切的感觉到,游戏编程玩的都是设计模式。架构没预先设计好,强耦合性代码在后期维护简直灾难。
大型单页应用里,复杂度上升到一定程度时,没有适当的设计模式进行降耦,后续的开发也难以下手。
而设计模式正是为了降耦而存在。
参考《javascript设计模式》——曾探
函数节流
var throttle = function(fn, interval){ var _self = fn, timer, firstTime = true; return function(){ var args = arguments. _me = this; if( firstTime ){ _self.apply(_me, args); return first } if(timer){ return false; } timer = setTimeout(function(){ clearTimeout(timer); timer = null; _self.apply(_me, args); }, interval || 500); } }window.onresize = throttle(function){ console.log(1);}, 500);
分式函数
var timeChunk = function(arr, fn, count){ var obj, t; var len = ary.length; var start = function(){ for(var i = 0; i { createSingleCreateLayer();}
策略模式
定义:封装一系列算法,并使其可以相互替换
计算工资Demo:
var strategies = { 'S': function(salary){ return salary * 4; }, 'A': function(salary){ return salary * 3; }}var calculateBonus = (level, salary) => { return strategies[level](salary);}
表单添加多种校验规则:
/*--------------- Strategies --------------*/var strategies = { isNotEmpth: (value, errorMsg) => { if(value == ''){ return errorMsg; } }, minLength: (value, length,errorMsg) => { if(value.length { this.cache = [];}Validator.prototype.add = (dom, rules) => { var self = this; for(var i = 0; rule; rule = rules[i++]){ ((rule) => { var strategyAry = strategy.split(':'); var errorMsg = rule.errorMsg; self.cache.push(function(){ var strategy = strategyAry.shift(); strategyAry.unshift(dom.value); strategyAry.push(errorMsg); return strategies[strategy].apply(dom, strategyAry); }); })(rule); }};Validator.prototype.start = () => { for(var i = 0; validatorFunc; validatorFunc = this.cache[i++]){ var errorMsg = validatorFunc(); if( errorMsg ){ return errorMsg; } }}/*-------------- 客户端调用 ------------*/var registerForm = document.getElementById('registerForm');var validataFunc = () => { var validator = new Validator(); validator.add(registorForm.username, [{ strategy: 'isNotEmpty', errorMsg: '用户名不能为空' },{ strategy: 'minLength', errorMsg: ‘最下长度为6’ }]); validator.add(registorForm.password, [{ strategy: 'minLength', errorMsg: '最小长度' }]) var errorMsg = validator.start(); return errorMsg;}registerForm.onsubmit = () => { var errorMsg = validataFunc(); if(errorMsg){ alert(errorMsg); return false; }}
代理模式
为一个对象提供一个代用品或者占位符,以便控制它的访问
面向对象设计原则——单一职责原则。面向对象设计鼓励将行为分布到细粒度的对象之中。
大量计算时加入代理作为缓存,异步请求时同理可用缓存:
var mult = () => { var a = 1; for(var i = 0, l = arguments.length; i { var cache = {}; return () => { var args = Array.prototype.join.call(arguments, ','); if( args in cache ){ return cache[args]; } return cache[args] = mult.apply(this, arguments); }})();
高阶函数动态创建代理
var mult = () => { var a = 1; for(var i = 0, l = arguments.length; i { var a = 0; for(var i = 0, l = arguments.length; i { var cache = {}; return () => { var args = Array.prototype.join.call(arguments, ','); if(args in cache){ return cache[args]; } return cache[args] = fn.apply(this, arguments); }}
迭代器模式
迭代器模式指提供一种方法顺序访问一个聚合对象的各个元素,又不暴露该对象的内部表示。
通用外部迭代器:
var Iterator = (obj) => { var current = 0; var next = () => { ++current; } var isDone = () => { return current >= obj.length; } var getCurrItem = () => { return obj[current]; } return { next: next, isDone: isDone, getCurrItem: getCurrItem }}
发布-订阅模式
var event = { clientListh: [], listen: function(key, fn){ if(!this.clientListh[key]){ this.clientList[key] = []; } this.clientList[key].push(fn); }, trigger: function(){ var key = Array.prototype.shift.call(arguments), fns = this.clientList[key]; if(!fns || fns.length === 0){ return false; } for(var i = 0; fn; fn = fns[i++]){ fn.apply(this.arguments); } }}var installEvent = function(obj){ for(var i in event){ obj[i] = event[i]; }};var salesOffices = {};installEvnet(salesOffices);salesOffices.listen('squareMeter88', function(price){ console.log('price': + price);})salesOfffices.trigger('squareMeter88', 20000);
发布——订阅模式可以很大程度降低耦合性,但滥用也会造成背后逻辑混乱,且浪费内存。
命令模式
主要是回调函数的的面向对象的替代品
没看懂命令模式有什么意义
撤销和重做
var commandStack = [];document.onkeypress = (ev)=>{ var keyCode = ev.keyCode, command = makeCommand(Ryu, commands[keyCode]); if(command){ command(); commandStack.push(command); }}$('# replay').onclick = ()=>{ var command; while(command = commandStack.shift()){ command(); }}
宏命令
var closeDoorCommand = { excute: ()=> { console.lg('close door'); }}var openPcCommand = { excute: ()=> { console.log('open pc'); }}var MacroCommand = ()=> { return { conmandList: [], add: (command)=>{ this.commandList.push(command); }, execute: ()=>{ for(var i = 0, command; command = this.commandsList[i++]; ){ command.execute(); } } }}
组合模式
类似命令模式的加强版,也是看不懂深层意义
遍历文件夹
/ Folder /var Folder = (name)=>{ this.name = name; this.parent = null; this.files = [];};Folder.prototype.add = (file)=> { file.parent = this; this.files.push(file);}Folder.prototype.scan = ()=>{ console.log('Begin scan: ' + this.name); for(var i = 0, file = this.files; file = files[i++]; ){ file.scan(); }}Folder.prototype.remove = ()=>{ if(!this.parent){ return; } for(var files = this.parent.files, l = files.length-1; l >= 0; l--){ var file = files[l]; if(file === this){ files.splice(l, 1); } }}/ File /var File = (name)=>{ this.name = name; this.parent = null;}File.prototype.add = ()=>{ throw new Error('Can not add file under file');}File.prototype.scan = ()=>{ console.log('Begin Scan: ' + this.name);}File.prototype.remove = ()=>{ if(!this.parent){ return; } for(var files = this.parent.files, l = files.length-1; l >= 0; l--){ var file = files[l]; if(file == this);{ file.splice(l, 1); } }}
模板方法模式
基于继承的设计模式
模板方法模式友抽象父类和具体实现的子类组成。父类封装了子类的算法框架,子类通过集成抽象类,也继承了整个算法框架。
钩子方法
var Bevrage = function(){}Beverage.prototype.boilWater = function(){ console.log('把水煮沸');}Beverage.prototype.brew = function(){ throw new Error('Class brew musth be rewrited');}....Beverage.prototype.addCondiments = function(){ throw new Error('adCondiments must be rewrited');}Beverage.prototype.customerWantsCondiments = function(){ return true;}Beverage.prototype.init = function(){ this.boilWater(); this.brew(); .... if(this.customerWantsCondiments()){ this.addCondiments(); } }var CoffeeWithHook = function(){};CoffeeWithHook.prototype = new Beverage();CoffeeWithHook.prototype.brew = function(){ console.log('brew coffee with water');};CoffeeWithHook.prototype.customerWantsCondiments = function(){ return widow.confirm('需要调料嘛?');}var coffeeWithHook = new CoffeeWithHook();coffeeWithHook.init();
高阶函数可以更方便的实现上面的demo...
享元模式
用于性能优化,核心是运用共享技术来支持大量细粒度的对象。
通用对象池的实现
var objectPoolFactory = (createObjFn)=>{ var objectPool = []; return{ create: function(){ var obj = objectPool.length === 0 ? createObjFn.apply(this, arguments) : objectPool.shift(); return obj; }, recover: (obj){ objectPool.push(obj); } }}
职责链模式
用来重构代码挺方便的。
把不同功能函数包装成链式节点再调用。
var order500 = function(orderType, pay, stock){ if(orderType == 1 && pay == true){ conosle.log('500, 100优惠券') } else{ return 'nextSuccessor'; // 把请求往后传递 } }var order200 = function(orderTYPE, pay, stock){ if(orderType == 2 && pay ==true){ console.log('200, 50优惠券'); } else{ return 'nextSuccessor'; }}var orderNormal = function(orderType, pay, stock){ if(stock > 0){ console.log('普通购买,无优惠券'); } else{ console.log('库存不足'); }}//职责链包装函数//Chain.prototype.setNextSuccessor 指定在链中的下一个结点//Chain.prototype.passRequest 请求传递给某个结点var Chain = function(fn){ this.fn = fn; this.successor = null;}Chain.prototype.setNextSuccessor = function(successor){ return this.successor = seccussor;}Chain.prototype.passRequest = function(){ var ret = this.fn.apply(this, arguments); if(ret === 'nextSuccessor'){ return this.successor && this.seccessor.passRequest.apply(this.successor, arguments); } return ret;}//将订单函数包装进职责链var chainOrder500 = new Chain(order500);var chainOrder200 = new Chain(order200);var chainOrderNormal = new Chain(orderNormal);chainOrder500.setNextSuccessor(chainOrder200);ChainOrder200.setNextSuccessor(chainOrderNormal);//Test]chainOrder500.pasRequest(1, true, 500);
中介者模式
个人感觉有点像代理模式.用一个中介对象,来处理其他对象的时间,以实现解耦的目的。
但缺点也很明显,当系统复杂到一定程度时,中介者对象慢慢会变成一个难以维护的对象
装饰者模式
动态的给类添加职责
关键字:JavaScript, 设计模式, var, return
版权声明
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!