javascript
模式(一)javascript设计模式
模式有三種:Architectural Pattern、Design Pattern、Coding Pattern,即:框架模式、設(shè)計(jì)模式、編程模式。本文主要講解javascript中的設(shè)計(jì)模式,好的設(shè)計(jì)模式能夠提高代碼的重用性,可讀性,使代碼更容易的維護(hù)和擴(kuò)展。本文適合有一點(diǎn)javascript基礎(chǔ),對(duì)javascript的概念有所了解。
一、單例模式:
?單例模式是javascript中最常用的模式,它是將自己的代碼放在一個(gè)命名空間下,這樣的好處是可以減少使用全局變量,在多人協(xié)同開發(fā)時(shí)也能避免命名沖突等問題。這樣的好處是維護(hù)起來非常方便,如下例:
1 var m = { 2 name: 'dog', 3 action: function() { 4 console.log(this.name); 5 } 6 }; 7 m.action();//調(diào)用?
或者
1 var dog = function() { 2 this.name = 'dog'; 3 this.action = function() { 4 return console.log(this.name); 5 }; 6 action(); 7 }; 8 dog(); //調(diào)用?
工廠模式:
工廠模式就是將對(duì)象的方法創(chuàng)建交給外部對(duì)象,這樣的好處就是解決了對(duì)象之間的相互影響、即耦合,避免了使用new來實(shí)例化對(duì)象,有助于創(chuàng)建模塊化的代碼,維護(hù)起來也方便。?工廠模式分為簡(jiǎn)單工廠模式和抽象工廠模式,下面介紹簡(jiǎn)單工廠模式:
1 var m = {}; 2 m.action = function() { 3 console.log('dog'); 4 }; 5 var demo = function() { 6 m.action(); 7 }; 8 demo()//調(diào)用?
抽象工廠模式先設(shè)計(jì)一個(gè)抽象類,這個(gè)類不能被實(shí)例化,只能用來派生子類,最后通過對(duì)子類的擴(kuò)展實(shí)現(xiàn)工廠方法。如下:
1 var f = function() {}; 2 f.prototype = { 3 c: function() { 4 throw new Error('can\'t use this method');//如果調(diào)用此方法會(huì)報(bào)錯(cuò),因?yàn)樗怯脕砼缮宇惒荒軐?shí)例化 5 } 6 }; 7 var e = function() { 8 f.call(this); 9 } 10 e.prototype = new f(); 11 e.prototype.constructor = e; 12 e.prototype.c = function() { 13 console.log('this method is redefine'); 14 } 15 // 調(diào)用 16 var demo = new e(); 17 demo.c();?
橋接模式:
橋接模式是將抽象與實(shí)現(xiàn)隔離,一遍二者獨(dú)立變化。在設(shè)計(jì)一個(gè)javascript API的時(shí)候,它可以用來弱化類和對(duì)象之間的耦合。它還可以用來把多個(gè)類聯(lián)接在一起。例如:
1 var class1 = function(a,b,c) { 2 this.a = a; 3 this.b = b; 4 this.c = c; 5 }; 6 var class2 = function(d) { 7 this.d = d; 8 }; 9 var demo = function(a,b,c,d) { 10 this.one = new Class1(a,b,c); 11 this.two = new Class2(d); 12 };?
組合模式:
組合模式可以用一條命令在多個(gè)對(duì)象上激發(fā)復(fù)雜的或遞歸的行為。好處是可以用同樣的發(fā)放處理對(duì)象的集合與其中的特定子對(duì)象,也可以用來把一批子對(duì)象組織成樹形結(jié)構(gòu),并且使整個(gè)樹都可被遍歷。如下:
1 // DynamicGallery Class 2 var DynamicGallery =function (id) { // 實(shí)現(xiàn)Composite,GalleryItem組合對(duì)象類 3 this.children = []; 4 this.element = document.createElement('div'); 5 this.element.id = id; 6 this.element.className ='dynamic-gallery'; 7 } 8 DynamicGallery.prototype = { 9 // 實(shí)現(xiàn)Composite組合對(duì)象接口 10 add: function (child) { 11 this.children.push(child); 12 this.element.appendChild(child.getElement()); 13 }, 14 remove: function (child) { 15 for (var node, i =0; node =this.getChild(i); i++) { 16 if (node == child) { 17 this.children.splice(i, 1); 18 break; 19 } 20 } 21 this.element.removeChild(child.getElement()); 22 }, 23 getChild: function (i) { 24 returnthis.children[i]; 25 }, 26 // 實(shí)現(xiàn)DynamicGallery組合對(duì)象接口 27 hide: function () { 28 for (var node, i =0; node =this.getChild(i); i++) { 29 node.hide(); 30 } 31 this.element.style.display ='none'; 32 }, 33 show: function () { 34 this.element.style.display ='block'; 35 for (var node, i =0; node = getChild(i); i++) { 36 node.show(); 37 } 38 }, 39 // 幫助方法 40 getElement: function () { 41 returnthis.element; 42 } 43 }?
1 var GalleryImage =function (src) { // 實(shí)現(xiàn)Composite和GalleryItem組合對(duì)象中所定義的方法 2 this.element = document.createElement('img'); 3 this.element.className ='gallery-image'; 4 this.element.src = src; 5 } 6 GalleryImage.prototype = { 7 // 實(shí)現(xiàn)Composite接口 8 // 這些是葉結(jié)點(diǎn),所以我們不用實(shí)現(xiàn)這些方法,我們只需要定義即可 9 add: function () { }, 10 remove: function () { }, 11 getChild: function () { }, 12 // 實(shí)現(xiàn)GalleryItem接口 13 hide: function () { 14 this.element.style.display ='none'; 15 }, 16 show: function () { 17 this.element.style.display =''; 18 }, 19 // 幫助方法 20 getElement: function () { 21 returnthis.element; 22 } 23 } 1 var topGallery =new DynamicGallery('top-gallery'); 2 topGallery.add(new GalleryImage('/img/image-1.jpg')); 3 topGallery.add(new GalleryImage('/img/image-2.jpg')); 4 topGallery.add(new GalleryImage('/img/image-3.jpg')); 5 var vacationPhotos =new DyamicGallery('vacation-photos'); 6 for(var i =0, i <30; i++){ 7 vacationPhotos.add(new GalleryImage('/img/vac/image-'+ i +'.jpg')); 8 } 9 topGallery.add(vacationPhotos); 10 topGallery.show(); 11 vacationPhotos.hide();?
門面模式:
門面模式常常是開發(fā)人員最親密的朋友,他幾乎是所有javascript庫(kù)的核心原則。門面模式有兩個(gè)作用:一是簡(jiǎn)化類的接口;二是消除類與使用它的客戶代碼之間的耦合。示例如下:
1 function a() { 2 3 } 4 function b() { 5 6 } 7 function ab() { 8 a(); 9 b(); 10 }?
適配器模式:
適配器模式可以用來在現(xiàn)有接口和不兼容的類之間進(jìn)行適配。從表面上看,適配器模式很像門面模式,都對(duì)別的對(duì)象進(jìn)行包裝并改變其呈現(xiàn)的接口。二者的區(qū)別在與它們?nèi)绾胃淖兘涌?#xff0c;門面元素展現(xiàn)的是一個(gè)簡(jiǎn)化的接口,它并不提供額外的選擇,而且有時(shí)為了方便完成常見任務(wù)它還會(huì)做出一些假定。而適配器則要把一個(gè)接口轉(zhuǎn)換為另一個(gè)接口,它并不會(huì)過濾某些能力,也不會(huì)簡(jiǎn)化接口。
1 var str = { 2 a: 'a', 3 b: 'b', 4 c: 'c' 5 }; 6 function i(s1,s2,s3) { 7 console.log(s1 + ',' + s2 + ',' + s3); 8 } 9 function demo(o) { 10 i(o.a,o.b,o.c); 11 }?
裝飾者模式:
裝飾者模式可用來透明地把對(duì)象包裝在具有同樣接口的另一個(gè)對(duì)象之中,裝飾者可以用于為對(duì)象添加功能,可以用來代替大量子類。裝飾者模式和組合模式有很多共同點(diǎn),它們都與所包裝的對(duì)象實(shí)現(xiàn)統(tǒng)一的接口并且會(huì)把任何方法條用傳遞給這些對(duì)象。可是組合模式用于把眾多子對(duì)象組織為一個(gè)整體,而裝飾者模式用于在不修改現(xiàn)有對(duì)象或從派生子類的前提下為其添加方法。如下:
1 var m = {}; 2 m.child = {}; 3 m.child.one = function() {}; 4 m.child.two = function() {};?
?享元模式:
?享元模式最適合于解決因創(chuàng)建大量類似對(duì)象而累及性能的問題。通過把大量獨(dú)立對(duì)象轉(zhuǎn)化為少量共享對(duì)象,可以降低運(yùn)行web應(yīng)用程序所需的資源數(shù)量。
javascript設(shè)計(jì)模式中的示例:
1 //汽車登記示例 2 var Car =function(make,model,year,owner,tag,renewDate){ 3 this.make=make; 4 this.model=model; 5 this.year=year; 6 this.owner=owner; 7 this.tag=tag; 8 this.renewDate=renewDate; 9 } 10 Car.prototype = { 11 getMake:function(){ 12 returnthis.make; 13 }, 14 getModel:function(){ 15 returnthis.model; 16 }, 17 getYear:function(){ 18 returnthis.year; 19 }, 20 transferOwner:function(owner,tag,renewDate){ 21 this.owner=owner; 22 this.tag=tag; 23 this.renewDate=renewDate; 24 }, 25 renewRegistration:function(renewDate){ 26 this.renewDate=renewDate; 27 } 28 } 29 //數(shù)據(jù)量小到?jīng)]多大的影響,數(shù)據(jù)量大的時(shí)候?qū)τ?jì)算機(jī)內(nèi)存會(huì)產(chǎn)生壓力,下面介紹享元模式優(yōu)化后 30 //包含核心數(shù)據(jù)的Car類 31 var Car=function(make,model,year){ 32 this.make=make; 33 this.model=model; 34 this.year=year; 35 } 36 Car.prototype={ 37 getMake:function(){ 38 returnthis.make; 39 }, 40 getModel:function(){ 41 returnthis.model; 42 }, 43 getYear:function(){ 44 returnthis.year; 45 } 46 } 47 //中間對(duì)象,用來實(shí)例化Car類 48 var CarFactory=(function(){ 49 var createdCars = {}; 50 return { 51 createCar:function(make,model,year){ 52 var car=createdCars[make+"-"+model+"-"+year]; 53 return car ? car : createdCars[make +'-'+ model +'-'+ year] =(new Car(make,model,year)); 54 } 55 } 56 })(); 57 //數(shù)據(jù)工廠,用來處理Car的實(shí)例化和整合附加數(shù)據(jù) 58 var CarRecordManager = (function() { 59 var carRecordDatabase = {}; 60 return { 61 addCarRecord:function(make,model,year,owner,tag,renewDate){ 62 var car = CarFactory.createCar(make, model, year); 63 carRecordDatabase[tag]={ 64 owner:owner, 65 tag:tag, 66 renewDate:renewDate, 67 car:car 68 } 69 }, 70 transferOwnership:function(tag, newOwner, newTag, newRenewDate){ 71 var record=carRecordDatabase[tag]; 72 record.owner = newOwner; 73 record.tag = newTag; 74 record.renewDate = newRenewDate; 75 }, 76 renewRegistration:function(tag,newRenewDate){ 77 carRecordDatabase[tag].renewDate=newRenewDate; 78 }, 79 getCarInfo:function(tag){ 80 return carRecordDatabase[tag]; 81 } 82 } 83 })();?
代理模式:
代理是一個(gè)對(duì)象,它可以用來控制對(duì)另一個(gè)對(duì)象的訪問。它與另外那個(gè)對(duì)象實(shí)現(xiàn)了同樣的接口,并且會(huì)把任何方法調(diào)用傳遞給那個(gè)對(duì)象。代理模式適合處理實(shí)例化比較費(fèi)時(shí)的本體,也適合處理那些需要較長(zhǎng)時(shí)間才能把數(shù)據(jù)載入用戶界面的類。
javascript設(shè)計(jì)模式中的示例:
1 var Publication =new Interface('Publication', ['getIsbn', 'setIsbn', 'getTitle', 'setTitle', 'getAuthor', 'setAuthor', 'display']); 2 var Book =function(isbn, title, author) { 3 //... 4 } 5 // implements Publication 6 implements(Book,Publication); 7 8 /* Library interface. */ 9 var Library =new Interface('Library', ['findBooks', 'checkoutBook', 'returnBook']); 10 11 /* PublicLibrary class. */ 12 var PublicLibrary =function(books) { 13 //... 14 }; 15 // implements Library 16 implements(PublicLibrary,Library); 17 18 PublicLibrary.prototype = { 19 findBooks: function(searchString) { 20 //... 21 }, 22 checkoutBook: function(book) { 23 //... 24 }, 25 returnBook: function(book) { 26 //... 27 } 28 }; 29 30 /* PublicLibraryProxy class, a useless proxy. */ 31 var PublicLibraryProxy =function(catalog) { 32 this.library =new PublicLibrary(catalog); 33 }; 34 // implements Library 35 implements(PublicLibraryProxy,Library); 36 37 PublicLibraryProxy.prototype = { 38 findBooks: function(searchString) { 39 returnthis.library.findBooks(searchString); 40 }, 41 checkoutBook: function(book) { 42 returnthis.library.checkoutBook(book); 43 }, 44 returnBook: function(book) { 45 returnthis.library.returnBook(book); 46 } 47 };?
觀察者模式:
觀察者模式是一種管理人與其任務(wù)之間的關(guān)系的得力工具。觀察者模式中存在兩個(gè)角色:觀察者和被觀察者。這種模式的好處是你可以對(duì)程序中某個(gè)對(duì)象的狀態(tài)進(jìn)行觀察,并且在其發(fā)生改變時(shí)能夠得到通知。
1 var f1 =function(){ 2 //code 3 } 4 var f2 =function(){ 5 //code 6 } 7 addEvent(element,'click',f1); 8 addEvent(element,'click',f2) 9 10 11 element.onclick = f1; 12 element.onclick = f2;?
命令模式:
命令模式可以用來對(duì)方法調(diào)用進(jìn)行參數(shù)化處理和傳送,經(jīng)這樣處理過的方法調(diào)用可以在任何需要的時(shí)候執(zhí)行。好處是可以用來消除調(diào)用操作的對(duì)象和實(shí)現(xiàn)操作的對(duì)象之間的耦合,使對(duì)象間的互動(dòng)方式更高的模塊化。這為各種具體的類更換帶來了極大的靈活性。
1 car Calculator={ 2 add:function(x,y){ 3 return x+y; 4 }, 5 substract:function(x,y){ 6 return x-y; 7 }, 8 multiply:function(x,y){ 9 return x*y; 10 }, 11 divide:function(x,y){ 12 return x/y; 13 } 14 } 15 Calculator.calc =function(command){ 16 return Calculator[command.type](command.op1,command.opd2) 17 }; 18 Calculator.calc({type:'add',op1:1,op2:1}); 19 Calculator.calc({type:'substract',op1:5,op2:2}); 20 Calculator.calc({type:'multiply',op1:5,op2:2}); 21 Calculator.calc({type:'divide',op1:8,op2:4});?
職責(zé)鏈模式:
職責(zé)鏈模式是通過實(shí)現(xiàn)一個(gè)由隱式地請(qǐng)求進(jìn)行處理對(duì)象組成的鏈而做到的。可以用來消除請(qǐng)求的發(fā)送者和接收者之間的耦合
javascript內(nèi)部就使用了這種模式來處理事件捕獲和冒泡的問題。
職責(zé)鏈由多個(gè)不同類型的對(duì)象組成:發(fā)送者是發(fā)出請(qǐng)求的對(duì)象,而接收者則是接收請(qǐng)求并且對(duì)其進(jìn)行處理或傳遞的對(duì)象,請(qǐng)求本身有時(shí)也是一個(gè)對(duì)象,它封裝著與操作有關(guān)的所有數(shù)據(jù)。其典型的流程大致是:
小結(jié):
每種模式都有自己的優(yōu)點(diǎn),選擇一種適合自己業(yè)務(wù)的模式非常重要,能夠提高代碼的可讀性、可維護(hù)性等等,希望本文能夠?qū)δ阌兴鶐椭?/p>
?
本文參考電子書《javascript設(shè)計(jì)模式》
?
轉(zhuǎn)載于:https://www.cnblogs.com/xiyangbaixue/p/3902699.html
總結(jié)
以上是生活随笔為你收集整理的模式(一)javascript设计模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: plc和pc串口通讯接线_电脑和PLC连
- 下一篇: JavaScript中奇妙的replac