摘要:架構沒預先設計好,強耦合性代碼在后期維護簡直災難。大型單頁應用里,復雜度上升到一定程度時,沒有適當的設計模式進行降耦,后續的開發也難以下手。而設計模式正是為了降耦而存在。面向對象設計鼓勵將行為分布到細粒度的對象之中。
在做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 < Math.min(coutn||1, arr.length); i++){ var obj = ary.shift(); fn(obj); } } return function(){ t = setInterval(function(){ if(ary.length === 0){ return clearInterval(t); } start(); }, 200); }; };惰性函數(重寫自重寫)
var addEvent = function(elem, type, handler){ if(window.addEventListener){ addEvent = function(elem, type, handler){ elem.addEventListener(type, handler, false); } } else if(window.addachEvent){ addEvent = function(elem, type, handler){ elem.attachEvent("on" + type, handler); } }
}
單例模式定義:保證類有且僅有一個實力,并提供全局訪問接口。
私有變量加下劃線 var _a = 1;通用惰性單例模式
把創建單例和管理單例的職責分開來:
var getSingle = function(fn){ var result; return function(){ return result || (result = fn.apply(this, arguments)); } } var createLayer = function(){ var div = document.createElement("div"); document.body.appendChild(div); } var createSingleCreateLayer = getSingle(createLayer); document.getElementById("#test").onclick = () => { 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 < length){ return errorMsg; } } } /*---------------- Validator ---------------*/ var Validator = () => { 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 < l; i++){ a = a * arguments[i]; } return a; } var proxyMult = (() => { 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 < l; i++){ a = a * arguments[i]; } return a; } var plus = () => { var a = 0; for(var i = 0, l = arguments.length; i < l; i++){ a = a + arguments[i]; } return a; } var createProxyFactory = (fn) => { 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);中介者模式
個人感覺有點像代理模式.用一個中介對象,來處理其他對象的時間,以實現解耦的目的。
但缺點也很明顯,當系統復雜到一定程度時,中介者對象慢慢會變成一個難以維護的對象
裝飾者模式動態的給類添加職責
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79649.html
摘要:寫在前面金三銀四又到了一年一度的跳槽季相信大家都在準備自己面試筆記我也針對自己工作中所掌握或了解的一些東西做了一個目錄總結方便自己復習詳細內容會在之后一一對應地補充上去有些在我的個人主頁筆記中也有相關記錄這里暫且放一個我的面試知識點目錄大家 寫在前面: 金三銀四, 又到了一年一度的跳槽季, 相信大家都在準備自己面試筆記, 我也針對自己工作中所掌握或了解的一些東西做了一個目錄總結,方便自...
摘要:寫在前面金三銀四又到了一年一度的跳槽季相信大家都在準備自己面試筆記我也針對自己工作中所掌握或了解的一些東西做了一個目錄總結方便自己復習詳細內容會在之后一一對應地補充上去有些在我的個人主頁筆記中也有相關記錄這里暫且放一個我的面試知識點目錄大家 寫在前面: 金三銀四, 又到了一年一度的跳槽季, 相信大家都在準備自己面試筆記, 我也針對自己工作中所掌握或了解的一些東西做了一個目錄總結,方便自...
摘要:因為同一時間,只能處理一個異步,這又牽扯到單線程問題了。然后控制臺默默打印了個目前前端,異步主要為前后端交互以及定時器,僅僅說前端,如果說的話,還有文件讀取等其他的方面會異步。 此篇文章完全按照我個人理解去寫。 1.何為JS 先說說js干啥的。不負責點說,js就是操作瀏覽器的。 有人可能說nodeJS,nodeJS嚴格意義上只能說是用的ES,因為他沒有dom ,也沒有bom。 簡單點說...
閱讀 2448·2021-10-14 09:42
閱讀 1138·2021-09-22 15:09
閱讀 3545·2021-09-09 09:33
閱讀 3026·2021-09-07 09:59
閱讀 3639·2021-09-03 10:34
閱讀 3532·2021-07-26 22:01
閱讀 2822·2019-08-30 13:06
閱讀 1203·2019-08-30 10:48