摘要:架構(gòu)沒預(yù)先設(shè)計(jì)好,強(qiáng)耦合性代碼在后期維護(hù)簡直災(zāi)難。大型單頁應(yīng)用里,復(fù)雜度上升到一定程度時,沒有適當(dāng)?shù)脑O(shè)計(jì)模式進(jìn)行降耦,后續(xù)的開發(fā)也難以下手。而設(shè)計(jì)模式正是為了降耦而存在。面向?qū)ο笤O(shè)計(jì)鼓勵將行為分布到細(xì)粒度的對象之中。
在做canvas、webGL游戲時,很深切的感覺到,游戲編程玩的都是設(shè)計(jì)模式。架構(gòu)沒預(yù)先設(shè)計(jì)好,強(qiáng)耦合性代碼在后期維護(hù)簡直災(zāi)難。
大型單頁應(yīng)用里,復(fù)雜度上升到一定程度時,沒有適當(dāng)?shù)脑O(shè)計(jì)模式進(jìn)行降耦,后續(xù)的開發(fā)也難以下手。
而設(shè)計(jì)模式正是為了降耦而存在。
參考《javascript設(shè)計(jì)模式》——曾探
函數(shù)節(jié)流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);分式函數(shù)
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); }; };惰性函數(shù)(重寫自重寫)
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); } }
}
單例模式定義:保證類有且僅有一個實(shí)力,并提供全局訪問接口。
私有變量加下劃線 var _a = 1;通用惰性單例模式
把創(chuàng)建單例和管理單例的職責(zé)分開來:
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(); }策略模式
定義:封裝一系列算法,并使其可以相互替換
計(jì)算工資Demo:
var strategies = { "S": function(salary){ return salary * 4; }, "A": function(salary){ return salary * 3; } } var calculateBonus = (level, salary) => { return strategies[level](salary); }
表單添加多種校驗(yàn)規(guī)則:
/*--------------- 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; } } } /*-------------- 客戶端調(diào)用 ------------*/ 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; } }代理模式
為一個對象提供一個代用品或者占位符,以便控制它的訪問
面向?qū)ο笤O(shè)計(jì)原則——單一職責(zé)原則。面向?qū)ο笤O(shè)計(jì)鼓勵將行為分布到細(xì)粒度的對象之中。
大量計(jì)算時加入代理作為緩存,異步請求時同理可用緩存:
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); } })();高階函數(shù)動態(tài)創(chuàng)建代理
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); } }迭代器模式
迭代器模式指提供一種方法順序訪問一個聚合對象的各個元素,又不暴露該對象的內(nèi)部表示。
通用外部迭代器:
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 } }發(fā)布-訂閱模式
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);
發(fā)布——訂閱模式可以很大程度降低耦合性,但濫用也會造成背后邏輯混亂,且浪費(fèi)內(nèi)存。
命令模式主要是回調(diào)函數(shù)的的面向?qū)ο蟮奶娲?/p>
沒看懂命令模式有什么意義
撤銷和重做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(); } } } }組合模式
類似命令模式的加強(qiáng)版,也是看不懂深層意義
遍歷文件夾
/************ 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); } } }模板方法模式
基于繼承的設(shè)計(jì)模式
模板方法模式友抽象父類和具體實(shí)現(xiàn)的子類組成。父類封裝了子類的算法框架,子類通過集成抽象類,也繼承了整個算法框架。
鉤子方法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("需要調(diào)料嘛?"); } var coffeeWithHook = new CoffeeWithHook(); coffeeWithHook.init();
高階函數(shù)可以更方便的實(shí)現(xiàn)上面的demo...
享元模式用于性能優(yōu)化,核心是運(yùn)用共享技術(shù)來支持大量細(xì)粒度的對象。
通用對象池的實(shí)現(xiàn)
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); } } }職責(zé)鏈模式
用來重構(gòu)代碼挺方便的。
把不同功能函數(shù)包裝成鏈?zhǔn)焦?jié)點(diǎn)再調(diào)用。
var order500 = function(orderType, pay, stock){ if(orderType == 1 && pay == true){ conosle.log("500, 100優(yōu)惠券") } else{ return "nextSuccessor"; // 把請求往后傳遞 } } var order200 = function(orderTYPE, pay, stock){ if(orderType == 2 && pay ==true){ console.log("200, 50優(yōu)惠券"); } else{ return "nextSuccessor"; } } var orderNormal = function(orderType, pay, stock){ if(stock > 0){ console.log("普通購買,無優(yōu)惠券"); } else{ console.log("庫存不足"); } } //職責(zé)鏈包裝函數(shù) //Chain.prototype.setNextSuccessor 指定在鏈中的下一個結(jié)點(diǎn) //Chain.prototype.passRequest 請求傳遞給某個結(jié)點(diǎn) 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; } //將訂單函數(shù)包裝進(jìn)職責(zé)鏈 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);中介者模式
個人感覺有點(diǎn)像代理模式.用一個中介對象,來處理其他對象的時間,以實(shí)現(xiàn)解耦的目的。
但缺點(diǎn)也很明顯,當(dāng)系統(tǒng)復(fù)雜到一定程度時,中介者對象慢慢會變成一個難以維護(hù)的對象
裝飾者模式動態(tài)的給類添加職責(zé)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/79649.html
摘要:寫在前面金三銀四又到了一年一度的跳槽季相信大家都在準(zhǔn)備自己面試筆記我也針對自己工作中所掌握或了解的一些東西做了一個目錄總結(jié)方便自己復(fù)習(xí)詳細(xì)內(nèi)容會在之后一一對應(yīng)地補(bǔ)充上去有些在我的個人主頁筆記中也有相關(guān)記錄這里暫且放一個我的面試知識點(diǎn)目錄大家 寫在前面: 金三銀四, 又到了一年一度的跳槽季, 相信大家都在準(zhǔn)備自己面試筆記, 我也針對自己工作中所掌握或了解的一些東西做了一個目錄總結(jié),方便自...
摘要:寫在前面金三銀四又到了一年一度的跳槽季相信大家都在準(zhǔn)備自己面試筆記我也針對自己工作中所掌握或了解的一些東西做了一個目錄總結(jié)方便自己復(fù)習(xí)詳細(xì)內(nèi)容會在之后一一對應(yīng)地補(bǔ)充上去有些在我的個人主頁筆記中也有相關(guān)記錄這里暫且放一個我的面試知識點(diǎn)目錄大家 寫在前面: 金三銀四, 又到了一年一度的跳槽季, 相信大家都在準(zhǔn)備自己面試筆記, 我也針對自己工作中所掌握或了解的一些東西做了一個目錄總結(jié),方便自...
摘要:因?yàn)橥粫r間,只能處理一個異步,這又牽扯到單線程問題了。然后控制臺默默打印了個目前前端,異步主要為前后端交互以及定時器,僅僅說前端,如果說的話,還有文件讀取等其他的方面會異步。 此篇文章完全按照我個人理解去寫。 1.何為JS 先說說js干啥的。不負(fù)責(zé)點(diǎn)說,js就是操作瀏覽器的。 有人可能說nodeJS,nodeJS嚴(yán)格意義上只能說是用的ES,因?yàn)樗麤]有dom ,也沒有bom。 簡單點(diǎn)說...
摘要:本文內(nèi)容共正則表達(dá)式火拼系列正則表達(dá)式回溯法原理學(xué)習(xí)正則表達(dá)式,是需要懂點(diǎn)兒匹配原理的。正則表達(dá)式迷你書問世了讓幫你生成和解析參數(shù)字符串最全正則表達(dá)式總結(jié)驗(yàn)證號手機(jī)號中文郵編身份證地址等是正則表達(dá)式的縮寫,作用是對字符串執(zhí)行模式匹配。 JS 的正則表達(dá)式 正則表達(dá)式 一種幾乎可以在所有的程序設(shè)計(jì)語言里和所有的計(jì)算機(jī)平臺上使用的文字處理工具。它可以用來查找特定的信息(搜索),也可以用來查...
閱讀 2512·2021-10-14 09:42
閱讀 1150·2021-09-22 15:09
閱讀 3556·2021-09-09 09:33
閱讀 3037·2021-09-07 09:59
閱讀 3652·2021-09-03 10:34
閱讀 3554·2021-07-26 22:01
閱讀 2836·2019-08-30 13:06
閱讀 1217·2019-08-30 10:48