摘要:訂閱模式的一個典型的應(yīng)用就是后面會寫一篇相關(guān)的讀書筆記。享元模式享元模式的核心思想是對象復(fù)用,減少對象數(shù)量,減少內(nèi)存開銷。適配器模式對目標(biāo)函數(shù)進(jìn)行數(shù)據(jù)參數(shù)轉(zhuǎn)化,使其符合目標(biāo)函數(shù)所需要的格式。
設(shè)計模式 單例模式
JS的單例模式有別于傳統(tǒng)面向?qū)ο笳Z言的單例模式,js作為一門無類的語言。使用全局變量的模式來實現(xiàn)單例模式思想。js里面的單例又分為普通單例和惰性單例,惰性單例指的是只有這個實例在需要被創(chuàng)建的時候才會被創(chuàng)建,創(chuàng)建后將始終保持這一個實例。
var getSingle = function (fn) { var result; return function () { return result || (result = fn.apply(this, arguments)); } };策略模式
定義:定義一系列的算法,把它們一個個的封裝起來,并且使他們可以相互替換。
策略模式至少由兩部分組成:第一個部分是一組策略類,用來封裝具體的算法,并負(fù)責(zé)計算過程;第二個部分是環(huán)境類,用于接受請求,并把請求委托給某一個策略類。策略模式,顧名思義就是指封裝一組組特定的算法,這些算法目的相同,用來實現(xiàn)不同條件下的特定要求。使用策略模式的優(yōu)點在于邏輯復(fù)用,代碼干凈,減少多重條件判斷語句的使用。比如:
const strategies = { S: (salary) => { return salary * 4; }, A: (salary) => { return salary * 3; }, B: (salary) => { return salary * 2; } } const calculateBouns = (key, salary) => { return strategies[key] && strategies[key](salary); } calculateBouns("S", 10000);代理模式 虛擬代理
虛擬代理在不改變原有函數(shù)(對象)的方法結(jié)構(gòu)的前提下,定義新的對象,并且實現(xiàn)同樣的接口,給被代理函數(shù)賦予額外的行為與邏輯,做一些過濾、合并、預(yù)處理等操作。
var myImage = (function () { var imgNode = document.createElement("img"); document.body.appendChild(imgNode); return function (src) { imgNode.src = src; } })(); var proxyImage = (function () { var img = new Image; img.onload = function () { myImage(this.src); }; return function (src) { myImage("loading.gif"); img.src = src; }; })();緩存代理
緩存代理可以為一些開銷大的運算結(jié)果提供暫時的緩存(適用純函數(shù)模式),在下次運算時,如果傳遞的參數(shù)和之前保持一致,則直接返回之前存儲的運算結(jié)果。
var createProxyFactory = function (fn) { var cache = {}; return function () { var args = Array.prototype.join.call(arguments, ","); if (args in cache) { return cache[args]; } return cache[args] = fn.apply(this, arguments); } }迭代器模式
類似數(shù)組的遍歷...
發(fā)布訂閱模式發(fā)布訂閱模式是一種典型的推模式,即主動向用戶推送數(shù)據(jù)的方式。一般的函數(shù)調(diào)用都是拉模式,即用戶主動獲取數(shù)據(jù)。訂閱模式的一個典型的應(yīng)用就是rxjs(后面會寫一篇相關(guān)的讀書筆記)。書中給出了一個最終版的代碼,但也是存在一定的局限性,具體實現(xiàn)需要按需解決。
var Event = (function () { var global = this, Event, _default = "default"; Event = function () { var _listen, _trigger, _remove, _slice = Array.prototype.slice, _shift = Array.prototype.shift, _unshift = Array.prototype.unshift, namespaceCache = {}, _create, find, // each方法綁定函數(shù)作用域為當(dāng)前數(shù)組項 each = function (ary, fn) { var ret; for (var i = 0, l = ary.length; i < l; i++) { var n = ary[i]; ret = fn.call(n, i, n); } return ret; }; _listen = function (key, fn, cache) { if (!cache[key]) { cache[key] = []; } cache[key].push(fn); }; _remove = function (key, cache, fn) { if (cache[key]) { if (fn) { for (var i = cache[key].length; i >= 0; i--) { if (cache[key][i] === fn) { cache[key].splice(i, 1); } } } else { cache[key] = []; } } }; _trigger = function () { var cache = _shift.call(arguments), key = _shift.call(arguments), args = arguments, _self = this, ret, stack = cache[key]; if (!stack || !stack.length) { return; } return each(stack, function () { return this.apply(_self, args); }); }; _create = function (namespace) { var namespace = namespace || _default; var cache = {}, offlineStack = [], ret = { listen: function (key, fn, last) { _listen(key, fn, cache); if (offlineStack === null) { return; } if (last === "last") { offlineStack.length && offlineStack.pop()(); } else { each(offlineStack, function () { this(); }); } offlineStack = null; }, one: function (key, fn, last) { _remove(key, cache); this.listen(key, fn, last); }, remove: function (key, fn) { _remove(key, cache, fn); }, trigger: function () { var fn, args, _self = this; _unshift.call(arguments, cache); args = arguments; fn = function () { return _trigger.apply(_self, args); }; if (offlineStack) { return offlineStack.push(fn); } return fn(); } }; return namespace ? (namespaceCache[namespace] ? namespaceCache[namespace] : namespaceCache[namespace] = ret) : ret; }; return { create: _create, one: function (key, fn, last) { var event = this.create(); event.one(key, fn, last); }, remove: function (key, fn) { var event = this.create(); event.remove(key, fn); }, listen: function (key, fn, last) { var event = this.create(); event.listen(key, fn, last); }, trigger: function () { var event = this.create(); event.trigger.apply(this, arguments); } }; }(); return Event; })();命令模式
定義一系列的算法,功能不同,將他們聚合成一個整體,作為命令接受者,再定義一個中間函數(shù),用來根據(jù)不同的指令調(diào)用接受者對象。而實際命令對象只需要來調(diào)用這個中間函數(shù)而無需直接和接受者交互。命令模式適用于邏輯撤銷邏輯回放的操作。
組合模式在父子鏈的函數(shù)上面實現(xiàn)相同的接口,在函數(shù)調(diào)用層面接口保持一致,具體函數(shù)邏輯各自獨立。組合模式可以讓我們使用樹形方式創(chuàng)建對象的結(jié)構(gòu)。我們可以把相同的操作應(yīng)用在組合對象和單個對象上。
模板方法模式定義一系列api執(zhí)行流程,相同部分由父函數(shù)實現(xiàn),不同部分api里面的具體操作交由傳入的函數(shù)決定。在js里面,會更多的去使用高階函數(shù)去替代。
享元模式享元模式的核心思想是對象復(fù)用,減少對象數(shù)量,減少內(nèi)存開銷。
職責(zé)鏈模式職責(zé)鏈模式的核心思想是,一個函數(shù),分為兩個部分,一部分:在符合條件的情況下,處理業(yè)務(wù)并結(jié)束傳遞;另外一部分,不符合條件,將業(yè)務(wù)處理轉(zhuǎn)交給下一個函數(shù),至于下個函數(shù)是誰,通過傳遞參數(shù)或者暴露接口來決定,而不是在函數(shù)內(nèi)部寫死。降低函數(shù)耦合性。
職責(zé)鏈的優(yōu)點是降低函數(shù)復(fù)雜度,缺點是過長的職責(zé)鏈可能會造成多段代碼閑置??赡芎芏嘀虚g鏈只起到傳遞參數(shù)的作用,降低了性能。
一些相互關(guān)聯(lián)的對象,對象與對象之間隔絕聯(lián)系,并且創(chuàng)建一個中間對象,將這些對象之間的聯(lián)系與關(guān)聯(lián)放在中間對象里面來處理。減少代碼耦合。
裝飾者模式裝飾者模式與代理模式類似,即在執(zhí)行目標(biāo)函數(shù)之前或者后進(jìn)行一些額外的操作,與代理模式的區(qū)別在于,裝飾者模式所做的操作不一定與目標(biāo)函數(shù)是一個類型的,所實現(xiàn)的功能也可能是千差萬別的。
狀態(tài)模式定義:允許一個對象在其內(nèi)部狀態(tài)改變時改變他它的行為,對象看起來似乎修改了它的類。適配器模式
狀態(tài)模式在其內(nèi)部包含了多種轉(zhuǎn)態(tài)對象,這些狀態(tài)對象有著相似的api,在調(diào)用這些api的時候,會動態(tài)修改狀態(tài)模式的當(dāng)前狀態(tài)。從而是狀態(tài)類的同一個api做出不同的反應(yīng)。
對目標(biāo)函數(shù)進(jìn)行數(shù)據(jù)參數(shù)轉(zhuǎn)化,使其符合目標(biāo)函數(shù)所需要的格式。
設(shè)計原則 單一職責(zé)原則一個對象只做一件事情。最少知識原則
一個軟件實體應(yīng)當(dāng)盡可能少的與其他實體發(fā)生相互作用。開放-封閉原則
當(dāng)需要改變一個程序的功能或者給這個程序增加新功能的時候,可以使用增加代碼的方式,但是不允許改動程序的源代碼。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/97777.html
摘要:設(shè)計模式與開發(fā)實踐讀書筆記最近利用碎片時間在上面閱讀設(shè)計模式與開發(fā)實踐讀書這本書,剛開始閱讀前兩章內(nèi)容,和大家分享下我覺得可以在項目中用的上的一些筆記。事件綁定暫時這么多,以后會不定期更新一些關(guān)于我讀這本書的筆記內(nèi)容 JavaScript 設(shè)計模式與開發(fā)實踐讀書筆記 最近利用碎片時間在 Kindle 上面閱讀《JavaScript 設(shè)計模式與開發(fā)實踐讀書》這本書,剛開始閱讀前兩章內(nèi)容,...
摘要:獨立出來的函數(shù)更加容易被改寫,減少維護(hù)成本。例如一個分頁函數(shù),函數(shù)接受一個表示挑戰(zhàn)頁碼,在跳轉(zhuǎn)前需要判斷是否在有效的取值范圍。面向?qū)ο笤O(shè)計鼓勵將行為分布在合理數(shù)量的更小對象之中。 這是《 javaScript設(shè)計模式與開發(fā)實踐 》一書的最后一章代碼重構(gòu)。 以下的一些方法不是必須嚴(yán)格遵守的標(biāo)準(zhǔn),選擇實踐哪些,以及如何實現(xiàn)這都需根據(jù)情況而定(是不是有充足時間) 提煉函數(shù) 如果在函數(shù)中有一...
摘要:除此以外,讓元素脫離文檔流也是一個很好的方法。因為元素一旦脫離文檔流,它對其他元素的影響幾乎為零,性能的損耗就能夠有效局限于一個較小的范圍。講完重排與重繪,往元素上綁定事件也是引起性能問題的元兇。高性能這本書非常精致,內(nèi)容也非常豐富。 showImg(https://segmentfault.com/img/bVJgbt?w=600&h=784); 入手《高性能JavaScript》一...
摘要:最近閱讀了編寫可維護(hù)的,在這里記錄一下讀書筆記。禁止使用,,,的字符串形式。避免使用級事件處理函數(shù)。讓事件處理程序成為接觸到對象的唯一函數(shù)。檢測函數(shù)是檢測檢測函數(shù)的最佳選擇。為特定瀏覽器的特性進(jìn)行測試,并僅當(dāng)特性存在時即可應(yīng)用特性檢測。 最近閱讀了《編寫可維護(hù)的 JavaScript》,在這里記錄一下讀書筆記。書中主要基于三個方向來講解怎么增加代碼的可維護(hù)性:編程風(fēng)格、編程實踐、自動化...
摘要:盡管在類庫中,可能會經(jīng)常用到通常和操作有關(guān),另外三種用法即使也非常罕見。一個通用的原則是,禁止使用,并且只在別無他法時使用,。和也是可以使用的,但不要用字符串形式而要用函數(shù) 再javascript中,eval()的參數(shù)是一個字符串,eval()會將傳入的字符串當(dāng)做代碼來執(zhí)行,開發(fā)者可以通過這個函數(shù)來載入外部的javascript代碼,活著隨機(jī)生成Javascript代碼并執(zhí)行它,比如:...
閱讀 1840·2021-09-22 15:23
閱讀 3269·2021-09-04 16:45
閱讀 1874·2021-07-29 14:49
閱讀 2773·2019-08-30 15:44
閱讀 1525·2019-08-29 16:36
閱讀 1044·2019-08-29 11:03
閱讀 1511·2019-08-26 13:53
閱讀 510·2019-08-26 11:57