javascript
模式(一)javascript设计模式
模式有三種:Architectural Pattern、Design Pattern、Coding Pattern,即:框架模式、設計模式、編程模式。本文主要講解javascript中的設計模式,好的設計模式能夠提高代碼的重用性,可讀性,使代碼更容易的維護和擴展。本文適合有一點javascript基礎,對javascript的概念有所了解。
一、單例模式:
?單例模式是javascript中最常用的模式,它是將自己的代碼放在一個命名空間下,這樣的好處是可以減少使用全局變量,在多人協同開發時也能避免命名沖突等問題。這樣的好處是維護起來非常方便,如下例:
1 var m = { 2 name: 'dog', 3 action: function() { 4 console.log(this.name); 5 } 6 }; 7 m.action();//調用?
或者
1 var dog = function() { 2 this.name = 'dog'; 3 this.action = function() { 4 return console.log(this.name); 5 }; 6 action(); 7 }; 8 dog(); //調用?
工廠模式:
工廠模式就是將對象的方法創建交給外部對象,這樣的好處就是解決了對象之間的相互影響、即耦合,避免了使用new來實例化對象,有助于創建模塊化的代碼,維護起來也方便。?工廠模式分為簡單工廠模式和抽象工廠模式,下面介紹簡單工廠模式:
1 var m = {}; 2 m.action = function() { 3 console.log('dog'); 4 }; 5 var demo = function() { 6 m.action(); 7 }; 8 demo()//調用?
抽象工廠模式先設計一個抽象類,這個類不能被實例化,只能用來派生子類,最后通過對子類的擴展實現工廠方法。如下:
1 var f = function() {}; 2 f.prototype = { 3 c: function() { 4 throw new Error('can\'t use this method');//如果調用此方法會報錯,因為它是用來派生子類不能實例化 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 // 調用 16 var demo = new e(); 17 demo.c();?
橋接模式:
橋接模式是將抽象與實現隔離,一遍二者獨立變化。在設計一個javascript API的時候,它可以用來弱化類和對象之間的耦合。它還可以用來把多個類聯接在一起。例如:
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 };?
組合模式:
組合模式可以用一條命令在多個對象上激發復雜的或遞歸的行為。好處是可以用同樣的發放處理對象的集合與其中的特定子對象,也可以用來把一批子對象組織成樹形結構,并且使整個樹都可被遍歷。如下:
1 // DynamicGallery Class 2 var DynamicGallery =function (id) { // 實現Composite,GalleryItem組合對象類 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 // 實現Composite組合對象接口 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 // 實現DynamicGallery組合對象接口 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) { // 實現Composite和GalleryItem組合對象中所定義的方法 2 this.element = document.createElement('img'); 3 this.element.className ='gallery-image'; 4 this.element.src = src; 5 } 6 GalleryImage.prototype = { 7 // 實現Composite接口 8 // 這些是葉結點,所以我們不用實現這些方法,我們只需要定義即可 9 add: function () { }, 10 remove: function () { }, 11 getChild: function () { }, 12 // 實現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();?
門面模式:
門面模式常常是開發人員最親密的朋友,他幾乎是所有javascript庫的核心原則。門面模式有兩個作用:一是簡化類的接口;二是消除類與使用它的客戶代碼之間的耦合。示例如下:
1 function a() { 2 3 } 4 function b() { 5 6 } 7 function ab() { 8 a(); 9 b(); 10 }?
適配器模式:
適配器模式可以用來在現有接口和不兼容的類之間進行適配。從表面上看,適配器模式很像門面模式,都對別的對象進行包裝并改變其呈現的接口。二者的區別在與它們如何改變接口,門面元素展現的是一個簡化的接口,它并不提供額外的選擇,而且有時為了方便完成常見任務它還會做出一些假定。而適配器則要把一個接口轉換為另一個接口,它并不會過濾某些能力,也不會簡化接口。
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 }?
裝飾者模式:
裝飾者模式可用來透明地把對象包裝在具有同樣接口的另一個對象之中,裝飾者可以用于為對象添加功能,可以用來代替大量子類。裝飾者模式和組合模式有很多共同點,它們都與所包裝的對象實現統一的接口并且會把任何方法條用傳遞給這些對象。可是組合模式用于把眾多子對象組織為一個整體,而裝飾者模式用于在不修改現有對象或從派生子類的前提下為其添加方法。如下:
1 var m = {}; 2 m.child = {}; 3 m.child.one = function() {}; 4 m.child.two = function() {};?
?享元模式:
?享元模式最適合于解決因創建大量類似對象而累及性能的問題。通過把大量獨立對象轉化為少量共享對象,可以降低運行web應用程序所需的資源數量。
javascript設計模式中的示例:
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 //數據量小到沒多大的影響,數據量大的時候對計算機內存會產生壓力,下面介紹享元模式優化后 30 //包含核心數據的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 //中間對象,用來實例化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 //數據工廠,用來處理Car的實例化和整合附加數據 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 })();?
代理模式:
代理是一個對象,它可以用來控制對另一個對象的訪問。它與另外那個對象實現了同樣的接口,并且會把任何方法調用傳遞給那個對象。代理模式適合處理實例化比較費時的本體,也適合處理那些需要較長時間才能把數據載入用戶界面的類。
javascript設計模式中的示例:
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 };?
觀察者模式:
觀察者模式是一種管理人與其任務之間的關系的得力工具。觀察者模式中存在兩個角色:觀察者和被觀察者。這種模式的好處是你可以對程序中某個對象的狀態進行觀察,并且在其發生改變時能夠得到通知。
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;?
命令模式:
命令模式可以用來對方法調用進行參數化處理和傳送,經這樣處理過的方法調用可以在任何需要的時候執行。好處是可以用來消除調用操作的對象和實現操作的對象之間的耦合,使對象間的互動方式更高的模塊化。這為各種具體的類更換帶來了極大的靈活性。
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});?
職責鏈模式:
職責鏈模式是通過實現一個由隱式地請求進行處理對象組成的鏈而做到的。可以用來消除請求的發送者和接收者之間的耦合
javascript內部就使用了這種模式來處理事件捕獲和冒泡的問題。
職責鏈由多個不同類型的對象組成:發送者是發出請求的對象,而接收者則是接收請求并且對其進行處理或傳遞的對象,請求本身有時也是一個對象,它封裝著與操作有關的所有數據。其典型的流程大致是:
小結:
每種模式都有自己的優點,選擇一種適合自己業務的模式非常重要,能夠提高代碼的可讀性、可維護性等等,希望本文能夠對你有所幫助。
?
本文參考電子書《javascript設計模式》
?
轉載于:https://www.cnblogs.com/xiyangbaixue/p/3902699.html
總結
以上是生活随笔為你收集整理的模式(一)javascript设计模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: plc和pc串口通讯接线_电脑和PLC连
- 下一篇: JavaScript中奇妙的replac