摘要:享元模式通過分析應用程序的對象,將其解析為內在數據和外在數據,減少對象數量,從而提高程序的性能。通過這種方式進行事件綁定,可以減少事件處理程序的數量,這種方式叫做事件委托,也是運用了享元模式的原理。事件處理程序是公用的內在部分,每個菜單項各
github 全文地址 : YOU-SHOULD-KNOW-JSJavaScript設計模式之外觀模式 概念
外觀模式:為一組復雜子系統接口提供一個更高級的統一接口,通過這個接口使得對子系統訪問更加的容易。
代碼演示// 使用外觀模式注冊事件監聽 function addEvent(dom,type,fn) { if(dom.addEventListener){ dom.addEventListener(type,fn,false); }else if(dom.attachEvent){ dom.attachEvent("on"+type,fn); }else{ dom["on"+type] = fn; } } // 使用外觀模式獲取事件對象 var getEvent = function(event) { return event || window.event; }
通過對接口的二次封裝,使其簡單易用,隱藏起內部的復雜度,外觀模式就是對接口的外層包裝,以供上層代碼調用。因此外觀模式封裝的接口方法不需要接口的具體實現,只需要按照接口的使用規則使用即可
JavaScript設計模式之適配器模式 概念適配器模式:將一個類的接口轉換為另外一個類的接口以滿足用戶的需求,使類之間的接口不兼容問題通過適配器得以解決。
代碼演示書中這里說的比價沒意思,這里我拿湯姆大叔的例子來說下
我們來舉一個例子,鴨子(Dock)有飛(fly)和嘎嘎叫(quack)的行為,而火雞雖然也有飛(fly)的行為,但是其叫聲是咯咯的(gobble)。如果你非要火雞也要實現嘎嘎叫(quack)這個動作,那我們可以復用鴨子的quack方法,但是具體的叫還應該是咯咯的,此時,我們就可以創建一個火雞的適配器,以便讓火雞也支持quack方法,其內部還是要調用gobble。
首先要先定義鴨子和火雞的抽象行為,也就是各自的方法函數:
//鴨子 var Duck = function(){ }; Duck.prototype.fly = function(){ throw new Error("該方法必須被重寫!"); }; Duck.prototype.quack = function(){ throw new Error("該方法必須被重寫!"); } //火雞 var Turkey = function(){ }; Turkey.prototype.fly = function(){ throw new Error(" 該方法必須被重寫 !"); }; Turkey.prototype.gobble = function(){ throw new Error(" 該方法必須被重寫 !"); }; //鴨子 var MallardDuck = function () { Duck.apply(this); }; MallardDuck.prototype = new Duck(); //原型是Duck MallardDuck.prototype.fly = function () { console.log("可以飛翔很長的距離!"); }; MallardDuck.prototype.quack = function () { console.log("嘎嘎!嘎嘎!"); }; //火雞 var WildTurkey = function () { Turkey.apply(this); }; WildTurkey.prototype = new Turkey(); //原型是Turkey WildTurkey.prototype.fly = function () { console.log("飛翔的距離貌似有點短!"); }; WildTurkey.prototype.gobble = function () { console.log("咯咯!咯咯!"); };
為了讓火雞也支持quack方法,我們創建了一個新的火雞適配器TurkeyAdapter:
var TurkeyAdapter = function(oTurkey){ Duck.apply(this); this.oTurkey = oTurkey; }; TurkeyAdapter.prototype = new Duck(); TurkeyAdapter.prototype.quack = function(){ this.oTurkey.gobble(); }; TurkeyAdapter.prototype.fly = function(){ var nFly = 0; var nLenFly = 5; for(; nFly < nLenFly;){ this.oTurkey.fly(); nFly = nFly + 1; } };
該構造函數接受一個火雞的實例對象,然后使用Duck進行apply,其適配器原型是Duck,然后要重新修改其原型的quack方法,以便內部調用oTurkey.gobble()方法。其fly方法也做了一些改變,讓火雞連續飛5次(內部也是調用自身的oTurkey.fly()方法)。
var oMallardDuck = new MallardDuck(); var oWildTurkey = new WildTurkey(); var oTurkeyAdapter = new TurkeyAdapter(oWildTurkey); //原有的鴨子行為 oMallardDuck.fly(); oMallardDuck.quack(); //原有的火雞行為 oWildTurkey.fly(); oWildTurkey.gobble(); //適配器火雞的行為(火雞調用鴨子的方法名稱) oTurkeyAdapter.fly(); oTurkeyAdapter.quack();JavaScript設計模式之代理模式 概念
代理模式:由于一個對象不能直接引用另一個對象,所以需要代理對象在這兩個對象之間起到中介的作用
代碼演示// 先聲明美女對象 var girl = function (name) { this.name = name; }; // 這是dudu var dudu = function (girl) { this.girl = girl; this.sendGift = function (gift) { alert("Hi " + girl.name + ", dudu送你一個禮物:" + gift); } }; // 大叔是代理 var proxyTom = function (girl) { this.girl = girl; this.sendGift = function (gift) { (new dudu(girl)).sendGift(gift); // 替dudu送花咯 } }; var proxy = new proxyTom(new girl("酸奶小妹")); proxy.sendGift("999朵玫瑰");
假如dudu要送酸奶小妹玫瑰花,卻不知道她的聯系方式或者不好意思,想委托大叔去送這些玫瑰,那大叔就是個代理
其實在日常開發中,我們遇到很多這種情況,比如跨域,之前總結過跨域的所有東西,其中的jsonp,window.name還是location.hash都是通過代理模式來實現的。
代理模式具體的從我的另一篇文章,JavaScript中的跨域總結去體會哈
JavaScript設計模式之裝飾著模式 概念裝飾著模式,在不改變源對象的基礎上,通過對其進行包裝拓展使原有對象可以滿足用戶的更復雜需求
代碼演示這里我拿給輸入框添加事件舉例
var decorator = function(input ,fn) { //獲取時間源 var input = document.getElementById(input); if(typeof input.onclick === "function"){ //緩存事件源原有的回調函數 var oldClickFn = input.onclick; input.onclick = function (ev) { oldClickFn(); fn(); } }else{ input.onclick = fn; } }
裝飾著模式很簡單,就是對原有對象的屬性和方法的添加。相比于之前說的適配器模式是對原有對象的適配,添加的方法和原有的方法功能上大致相似。但是裝飾著提供的方法和原有方法功能項則有一定的區別,且不需要去了解原有對象的功能。只要原封不動的去使用就行。不需要知道具體的實現細節。
JavaScript設計模式之橋接模式 概念橋接模式:在系統沿著多個維度變化的時候,不增加起復雜度已達到解耦的目的
應用場景在我們日常開發中,需要對相同的邏輯做抽象的處理。橋接模式就是為了解決這類的需求。
橋接模式最主要的特點就是將實現層和抽象層解耦分離,是兩部分可以獨立變化
比如我們寫一個跑步游戲,對于游戲中的人和精靈都是動作單元。而他們的動作也是非常的統一。比如人和精靈和球運動都是x,y坐標的改變,球的顏色和精靈的顏色繪制方式也非常的類似。
我們就可以將這些方法給抽象出來。
//運動單元 function Speed(x,y) { this.x = x; this.y = y; } Speed.prototype.run = function() { console.log("動起來"); } // 著色單元 function Color(cl) { this.color = cl; } Color.prototype.draw = function() { console.log("繪制色彩") } // 變形單元 function Shape(ap) { this.shape = ap; } Shape.prototype.change = function() { console.log("改變形狀"); } //說話單元 function Speak(wd) { this.word = wd; } Speak.prototype.say = function() { console.log("請開始你的表演") } //創建球類,并且它可以運動可以著色 function Ball(x,y,c) { this.speed = new Speed(x,y); this.color = new Color(c); } Ball.prototype.init = function() { //實現運動和著色 this.speed.run(); this.color.draw(); } function People(x,y,f) { this.speed = new Speed(x,y); this.speak = new Speak(f); } People.prototype.init = function() { this.speed.run(); this.speak.say(); } //... //當我們實例化一個人物對象的時候,他就可以有對應的方法實現了 var p =new People(10,12,"我是一個人"); p.init();JavaScript設計模式之組合模式 概念
組合模式:又稱部分-整體模式,將對象組合成樹形結構以表示成“部分整體”的層次結構。組合模式使得用戶對單個對象以及組合對象的使用具有一致性
使用場景我們平時開發過程中,一定會遇到這種情況:同時處理簡單對象和由簡單對象組成的復雜對象,這些簡單對象和復雜對象會組合成樹形結構,在客戶端對其處理的時候要保持一致性。比如電商網站中的產品訂單,每一張產品訂單可能有多個子訂單組合,比如操作系統的文件夾,每個文件夾有多個子文件夾或文件,我們作為用戶對其進行復制,刪除等操作時,不管是文件夾還是文件,對我們操作者來說是一樣的。在這種場景下,就非常適合使用組合模式來實現。
組合模式主要有三個角色:
(1)抽象組件(Component):抽象類,主要定義了參與組合的對象的公共接口
(2)子對象(Leaf):組成組合對象的最基本對象
(3)組合對象(Composite):由子對象組合起來的復雜對象
理解組合模式的關鍵是要理解組合模式對單個對象和組合對象使用的一致性,我們接下來說說組合模式的實現加深理解。
代碼演示// 抽象一個虛擬父類 var News = function() { this.children = []; this.element = null; } News.prototype = { init:function() { throw new Error("請重寫你的方法"); }, add:function() { throw new Error("請重寫你的方法"); }, getElement:function() { throw new Error("請重寫你的方法"); }, } function iniheritObject(o) { function F() {} F.prototype = o; return new F(); } function inheritPrototype(subClass,superClass) { var p = iniheritObject(superClass.prototype); p.constructor = subClass; subClass.prototype = p; } //容器類 var Container = function(id,parent) { News.call(this); this.id = id; this.parent = parent; this.init(); } //寄生式繼承父類原型方法 inheritPrototype(Container,News); Container.prototype.init = function() { this.element = document.createElement("ul"); this.element.id = this.id; this.element.className = "new-container"; } Container.prototype.add = function(child) { this.children.push(child); this.element.appendChild(child.getElement()); return this; } Container.prototype.getElement = function() { return this.element; } Container.prototype.show = function() { this.parent.appendChild(this.element) } //同樣下一層極的行成員集合類以及后面新聞組合體類 var Item = function(classname) { News.call(this); this.classname = classname; this.init(); } inheritPrototype(Item,News); Item.prototype.init = function() { this.element = document.createElement("li"); this.element.className = this.classname; } Item.prototype.add = function(child) { this.children.push(child); this.element.appendChild(child.getElement()); return this; } Item.prototype.getElement = function() { return this.element; } var NewsGroup = function(className) { News.call(this); this.classname = classname|| ""; this.init(); } inheritPrototype(NewsGroup,News); NewsGroup.prototype.init = function() { this.element = document.createElement("div"); this.element.className = this.classname; } NewsGroup.prototype.add = function(child) { this.children.push(child); this.element.appendChild(child.getElement()); return this; } NewsGroup.prototype.getElement = function() { return this.element; }
所以后面我們在使用的時候,創建新聞類,利用之前定義的組合元素去組合就可以了。
JavaScript設計模式之享元模式 概念享元模式:運用共享技術有效的支持大量細粒度對象,避免對象之間擁有相同內容造成的不必要開銷
主要用來優化程序的性能,適合解決大量類似的對象產生的性能問題。享元模式通過分析應用程序的對象,將其解析為內在數據和外在數據,減少對象數量,從而提高程序的性能。
基礎知識享元模式通過共享大量的細粒度的對象,減少對象的數量,從而減少對象的內存,提高應用程序的性能。其基本思想就是分解現有類似對象的組成,將其展開為可以共享的內在數據和不可共享的外在數據,我們稱內在數據的對象為享元對象。通常還需要一個工廠類來維護內在數據。
在JS中,享元模式主要有下面幾個角色組成:
客戶端:用來調用享元工廠來獲取內在數據的類,通常是應用程序所需的對象
享元工廠:用來維護享元數據的類
享元類:保持內在數據的類
基本實現我們舉個例子進行說明:蘋果公司批量生產iphone,iphone的大部分數據比如型號,屏幕都是一樣,少數部分數據比如內存有分16G,32G等。未使用享元模式前,我們寫代碼如下:
function Iphone(model, screen, memory, SN) { this. model = model; this.screen = screen; this.memory = memory; this.SN = SN; } var phones = []; for (var i = 0; i < 1000000; i++) { var memory = i % 2 == 0 ? 16 : 32; phones.push(new Iphone("iphone6s", 5.0, memory, i)); }
這段代碼中,創建了一百萬個iphone,每個iphone都獨立申請一個內存。但是我們仔細觀察可以看到,大部分iphone都是類似的,只是內存和序列號不一樣,如果是一個對性能要求比較高的程序,我們就要考慮去優化它。
大量相似對象的程序,我們就可以考慮用享元模式去優化它,我們分析出大部分的iphone的型號,屏幕,內存都是一樣的,那這部分數據就可以公用,就是享元模式中的內在數據,定義享元類如下:
function IphoneFlyweight(model, screen, memory) { this.model = model; this.screen = screen; this.memory = memory; }
我們定義了iphone的享元類,其中包含型號,屏幕和內存三個數據。我們還需要一個享元工廠來維護這些數據:
var flyweightFactory = (function () { var iphones = {}; return { get: function (model, screen, memory) { var key = model + screen + memory; if (!iphones[key]) { iphones[key] = new IphoneFlyweight(model, screen, memory); } return iphones[key]; } }; })();
在這個工廠中,我們定義了一個字典來保存享元對象,提供一個方法根據參數來獲取享元對象,如果字典中有則直接返回,沒有則創建一個返回。
接著我們創建一個客戶端類,這個客戶端類就是修改自iphone類:
function Iphone(model, screen, memory, SN) { this.flyweight = flyweightFactory.get(model, screen, memory); this.SN = SN; }
然后我們依舊像之間那樣生成多個iphone
var phones = []; for (var i = 0; i < 1000000; i++) { var memory = i % 2 == 0 ? 16 : 32; phones.push(new Iphone("iphone6s", 5.0, memory, i)); } console.log(phones);
這里的關鍵就在于Iphone構造函數里面的this.flyweight = flyweightFactory.get(model, screen, memory)。這句代碼通過享元工廠去獲取享元數據,而在享元工廠里面,如果已經存在相同數據的對象則會直接返回對象,多個iphone對象共享這部分相同的數據,所以原本類似的數據已經大大減少,減少的內存的占用。
在DOM中的使用點擊菜單項,進行相應的操作,我們通過jQuery來綁定事件,一般會這么做:
$(".item").on("click", function () { console.log($(this).text()); })
給每個列表項綁定事件,點擊輸出相應的文本。這樣看暫時沒有什么問題,但是如果是一個很長的列表,尤其是在移動端特別長的列表時,就會有性能問題,因為每個項都綁定了事件,都占用了內存。但是這些事件處理程序其實都是很類似的,我們就要對其優化。
$(".menu").on("click", ".item", function () { console.log($(this).text()); })
通過這種方式進行事件綁定,可以減少事件處理程序的數量,這種方式叫做事件委托,也是運用了享元模式的原理。事件處理程序是公用的內在部分,每個菜單項各自的文本就是外在部分。我們簡單說下事件委托的原理:點擊菜單項,事件會從li元素冒泡到ul元素,我們綁定事件到ul上,實際上就綁定了一個事件,然后通過事件參數event里面的target來判斷點擊的具體是哪一個元素,比如低級第一個li元素,event.target就是li,這樣就能拿到具體的點擊元素了,就可以根據不同元素進行不同的處理。
參考地址:http://luopq.com/2015/11/20/d...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/90419.html
摘要:本文最早為雙十一而作,原標題雙大前端工程師讀書清單,以付費的形式發布在上。發布完本次預告后,捕捉到了一個友善的吐槽讀書清單也要收費。這本書便從的異步編程講起,幫助我們設計快速響應的網絡應用,而非簡單的頁面。 本文最早為雙十一而作,原標題雙 11 大前端工程師讀書清單,以付費的形式發布在 GitChat 上。發布之后在讀者圈群聊中和讀者進行了深入的交流,現免費分享到這里,不足之處歡迎指教...
摘要:本文最早為雙十一而作,原標題雙大前端工程師讀書清單,以付費的形式發布在上。發布完本次預告后,捕捉到了一個友善的吐槽讀書清單也要收費。這本書便從的異步編程講起,幫助我們設計快速響應的網絡應用,而非簡單的頁面。 本文最早為雙十一而作,原標題雙 11 大前端工程師讀書清單,以付費的形式發布在 GitChat 上。發布之后在讀者圈群聊中和讀者進行了深入的交流,現免費分享到這里,不足之處歡迎指教...
摘要:本文最早為雙十一而作,原標題雙大前端工程師讀書清單,以付費的形式發布在上。發布完本次預告后,捕捉到了一個友善的吐槽讀書清單也要收費。這本書便從的異步編程講起,幫助我們設計快速響應的網絡應用,而非簡單的頁面。 本文最早為雙十一而作,原標題雙 11 大前端工程師讀書清單,以付費的形式發布在 GitChat 上。發布之后在讀者圈群聊中和讀者進行了深入的交流,現免費分享到這里,不足之處歡迎指教...
摘要:在面向對象的語言中,比如,等,單例模式通常是定義類時將構造函數設為,保證對象不能在外部被出來,同時給類定義一個靜態的方法,用來獲取或者創建這個唯一的實例。 萬事開頭難,作為正經歷菜鳥賽季的前端player,已經忘記第一次告訴自己要寫一些東西出來是多久以的事情了。。。如果,你也和我一樣,那就像我一樣,從現在開始,從看到這篇文章開始,打開電腦,敲下你的第一篇文章(或者任何形式的文字)吧。 ...
閱讀 2137·2023-04-25 18:49
閱讀 1840·2019-08-30 14:02
閱讀 2643·2019-08-29 17:24
閱讀 3323·2019-08-28 18:10
閱讀 2926·2019-08-28 18:03
閱讀 488·2019-08-26 12:01
閱讀 3309·2019-08-26 11:31
閱讀 1409·2019-08-26 10:29