亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > JavaScript > 正文

學習JavaScript設計模式(接口)

2024-05-06 16:25:21
字體:
來源:轉載
供稿:網友
這篇文章主要帶領大家學習JavaScript設計模式,其中重點介紹接口,舉例說明什么是接口,對接口進行詳細剖析,感興趣的小伙伴們可以參考一下
 

1、接口概述

1)、什么是接口?

接口是提供了一種用以說明一個對象應該具有哪些方法的手段。盡管它可以表明這些方法的語義,但它并不規定這些方法應該如何實現。

2)、 接口之利

  • 促進代碼的重用。

接口可以告訴程序員一個類實現了哪些方法,從而幫助其使用這個類。

  • 有助于穩定不同類之前的通信方式。
  • 測試和調式因此也能變得更輕松。

在javascript這種弱類型語言中,類型不匹配錯誤很難跟蹤。使用接口可以讓這種錯誤的查找變午更容易一點,因為此時如果一個對象不像所要求的類型,或者沒有實現必要的方法,那么你會得到包含有用信息的明確的錯誤提示。這樣一來,邏輯錯誤可以被限制在方法自身,而不是在對象構成之中。

  • 接口還能讓代碼變得更穩固.

因為對接口的任何改變在所有實現它的類都必須體現出來。如果接口添加了一個操作,而某個實現它的類并沒有相應的添加這個操作,那么你肯定會立即見到一個錯誤。

3)、接口之弊

javascript是一種具有極強表現圖片的語言,這主要得益于其弱類型的特點。而接口的使用則一定程序上強化了類型的作用。這降低了語言的靈活性。javascript并沒有提供對接口的內置支持,而試圖模仿其它語言內置的功能總會有一些風險。

js中接口使用的最大問題在于,無法強迫其他程序員遵守你定義的接口。在其它語言中,接口的概念是內置的,如果某人定義了實現一個接口的類,那么編譯器會確保該類的確實現了這個接口。而在javascript中則必須用手工的辦法保證某個類實現了一個接口。編碼規范和輔助類可以提供一些幫助,但無法徹底根除這個問題。如果項目的其他程序員不認真對待接口,那么這些接口的使用是無法得到強制性保證的。除非項目的所有人都同意使用接口并對其進行檢查,否則接口的很多價值都無從體現。

2、在javascript中模仿接口

javascript中模仿接口的三種方法:注解描述法、屬性檢查法、鴨式辨型法。

沒有哪種技術是完美的,但三者結合使用基本上可以令人滿意。

1)、注釋描述法實現接口

用注釋模仿接口是最簡單的方法,但效果卻是最差的。這種方法模仿其他頁面對象語言中的做法,使用了interface和implements關鍵字,但把它們放在注釋中,以免引起語法錯誤。如下:

 

//javascript中定義接口的方式有三種://1、注解描述的方式 /**    * interface Composite{* function add(obj);* function remove(obj);* function update(obj);}優點:程序員可以有參考缺點:缺點一大堆,他只是一個借口的文檔范疇,假如不實現   所有的方法,程序照樣可以運行,太松散了。對測試和調試難度大*/// Implement of interface Compositevar CompositeImpl =function(){ /*this.add = function(obj){  };  this.remove = function(obj){  };   這種函數定義的方法,在實例化一個對象的時候,new   一個示例,將產生一個方法,且各個實力的方法還不一樣。   所以采用下面的方法:  */  CompositeImpl.prototype.add = function(obj){  }  CompositeImpl.prototype.remove = function(obj){  }      CompositeImpl.prototype.update = function(obj){  }}var c1 = new CompositeImpl();var c2 = new CompositeImpl()alert(c1.add == c2.add)

這種模仿并不是很好。它沒有為確保Composite真正實現了正確的方法集而進行檢查,也不會拋出錯誤以告知程序員程序中的問題。說到底它主要還是屬于程序文檔范疇。在這種做法中,對接口約定的遵守完全依靠自覺。

2)、屬性檢測法實現接口

這種方法更嚴謹一點。所有類都明確地聲明自己實現了哪些接口,那些想與這些類打交道的對象可能針對這些聲明進行檢查。那些接口自身仍然只是注釋,但現在你可以通過檢查一個屬性得知某個類自稱實現了什么接口。

 

/**   * interface Composite{ *   function add(obj); *   function remove(obj); *   function update(obj); * } * interface FormItem{ *   function select(obj); * } */  // CompositeImpl implements interface Composite,FormItem  var CompositeImpl =function(){    //顯示在類的內部,接收所實現的接口,一般來說,這是一個規范,    // 我們項目經理:在內部類定義一個數組,名字要固定    this.interfaceImplments = ['Composite','FormItem'];    CompositeImpl.prototype.add = function(obj){       alert("小平果");  }  CompositeImpl.prototype.remove = function(obj){  }      CompositeImpl.prototype.update = function(obj){  }  /*CompositeImpl.prototype.select = function(obj){  }*/  }  //定義函數檢測,判斷當前對象是否實現了所有的接口  function checkCompositeImpl (instance){    if (!isImplments(instance,'Composite','FormItem')) {      throw new Error('Object cannot implements all the interface');    };  }  //公用的具體檢測方法(核心方法),主要目的就是判斷示例對象有沒有實現相關的接口;  function isImplments(object){    //arguments 對象會的函數的實際對象    for (var i = 1, len = arguments.length; i < len; i++) { //注意這里從1開始,逐個方法判斷。      var interfaceName = arguments[i];      //接收實現每一個接口的名字      var interfaceFound = false;//判斷此方法到底是實現了還是失敗了?規范里定義了interfaceImplments.      for (var j = 0;j < object.interfaceImplments.length; j++) {        if(object.interfaceImplments[j] == interfaceName){          interfaceFound = true;          break;        }      };       //如果沒有實現,則返回false       if (!interfaceFound) {          return false;       };    }     return true;  }var c1 = new CompositeImpl();checkCompositeImpl(c1);c1.add();

這個例子中,CompositeImpl 宣稱自己實現了Composite接口,其做法是把這兩個接口名稱加入一個名為implementsInterfaces的數組。類顯式聲明自己支持什么接口。任何一個要求基于參數屬于特定類型的函數都可以對這個屬性進行檢查,并在所需接口未在聲明之列時拋出一個錯誤。

這種方法有幾個優點。它對類所實現的接口提供了文檔說明。如果需要的接口不在一個類宣稱支持的接口之列,你會看到錯誤消息。通過利用這些錯誤,你可以強迫其他程序員聲明這些接口。

這種方法的主要缺點在于它并未確保類真正實現了自稱實現的接口。你只知道它是否說自己實現了接口。在創建一個類時聲明它實現了一個接口,但后來在實現該接口所規定的方法時卻漏掉其中的某一個,這種錯誤很常見。此時所有檢查都能通過,但那個方法卻不存在,這將在代碼中埋下一個隱患。另外顯式聲明類所支持的接口也需要一些額外的工作。

3)、鴨式辨型法實現接口

其實,類是否聲明自己支持哪些接口并不重要,只要它具有這些接口中的方法就行。鴨式辨型(這個名稱來自James Whitomb Riley的名言:“像鴨子一樣走路并且嘎嘎叫的就是鴨子”)正是基于這樣的認識。它把對象實現的方法集作作為判斷它是不是某個類的實例的唯一標準。這種技術在檢查一個類是否實現了某個接口時也可大顯向身手。這種方法背后的觀點很簡單:如果對象具有與接口定義的方法同名的所有方法,那么就可以認為它實現了這個接口。你可以用一個輔助函數來確保對象具有所有必需的方法:

 

/* 實現接口的第三種方式:鴨式辨型發實現接口,(較為完美的實現方法)   核心思想:一個類實現接口的主要目的:把其中的方法都實現了(檢測方法)   完全面向對象 代碼實現統一,實現解耦*///1、接口類---Class Interface ===>實例化N多個接口/** *接口類的參數?幾個 * 參數1:接口名 * 參數2:接收方法的集合(數組) */var Interface = function(name , methods){   //判斷接口的參數個數   if (arguments.length !=2) {     throw new Error('the instance interface constructor arguments should be 2');   };   this.name =name;   //this.methods = methods;   this.methods = [];   for (var i = 0, len = methods.length; i <len; i++) {     if (typeof methods[i] !== "string"){        throw new Error('the name of method is wrong');     }     this.methods.push(methods[i]);   } }//2、準備工作,具體的實現//(1)實例化接口對象var CompositeInterface = new Interface('CompositeInterface',['add','delete']);var FormItemInterface = new Interface('FormItemInterface',['update','select']); //(2)具體的實現類//CompositeImpl implments CompositionIterface FormItemIterfacevar CompositeImpl = function(){}//(3)實現接口的方法 implements methodsCompositeImpl.prototype.add = function(obj){  alert("add");}CompositeImpl.prototype.delete = function(obj){  alert("delete");}     CompositeImpl.prototype.update = function(obj){  alert("update");}/*CompositeImpl.prototype.select = function(obj){  alert("select");}*///3、檢驗接口里的方法//如果檢測通過,不做任何操作;不通過,則拋出異常。//這個方法的目的就是 檢測方法的Interface.ensureImplements =function(object){   //如果接受參數長度小于2 ,證明還有任何實現的接口   if (arguments.length < 2) {     throw new Error('The Interface has no implement class');   };   //獲得接口的實例對象  for (var i = 1, len= arguments.length; i < len; i++) {     var instanceInterface =arguments[i];     //判斷參數是否為 接口類的類型     if (instanceInterface.constructor !==Interface) {        throw new Error('The arguments constructor is not Interface Class');     };     for (var j = 0, len2 =instanceInterface.methods.length ; j <len2; j++ ) {        //用一個臨時變量 ,接收每個方法的名字(注意為字符串類型)        var methodName = instanceInterface.methods[j];        //object[key] 獲得方法        if (!object[methodName] || typeof object[methodName] !== 'function')        {          throw new Error('the method"'+ methodName+'"is not found');        }     }   }}var c1 =new CompositeImpl();Interface.ensureImplements(c1,CompositeInterface,FormItemInterface);c1.add();

與另外兩種方法不同,這種方法并不借助注釋。其各個方面都是可以強制實施的。ensureImplements函數需要至少兩個參數。第一個參數是想要檢查的對象。其余參數是據以對那個對象進行檢查的接口。該函數檢查其第一個參數代表的對象是否實現了那些接口所聲明的所有方法。如果發現漏掉了任何一個方法,它就會拋出錯誤,其中包含了所缺少的那個方法和未被正確實現的接口的名稱等有用信息。這種檢查可以用在代碼中任何需要確保某個對象實現了某個接口的地方。在本例中,addForm函數僅當一個表單對象支持所有必要的方法時才會對其執行添加操作。

盡管鴨式辨型可能是上述三種方法中最有用的一種,但它也有一些缺點。這種方法中,類并不聲明自己實現了哪些接口,這降低了代碼的可重用性,并且也缺乏其他兩種方法那樣的自我描述性。它需要使用一個輔助類Interface和一個輔助函數ensureImplements。而且,它只關心方法的名稱,并不檢查其參數的名稱、數目或類型。

3、Interface類的使用場合

嚴格的類型檢查并不總是明智的。許多js程序員根本不用接口或它所提供的那種檢查,也照樣一干多年。接口在運用設計模式實現復雜系統的時候最能體現其價值。它看似降低javascript的靈活性,而實際上,因為使用接口可以降低對象間的耦合程度,所以它提高了代碼的靈活性。接口可以讓函數變得更靈活,因為你既能向函數傳遞任何類型的參數,又能保證它只會使用那些具有必要方法的對象。

4、Interface類的用法

判斷代碼中使用接口是否劃算是最重要的一步。對于小型的、不太費事的項目來說,接口的好處也許并不明顯,只是徒增其復雜度而已。你需要自行權衡其利弊。如果認為在項目中使用接口利大于弊,那么可以參照如下使用說明: 
1)、 將Interface類納入HTML文件。 
2)、 逐一檢查代碼中所有以對象為參數的方法。搞清代碼正常運轉要求的這些對象參數具有哪些方法 
3)、 為你需要的每一個不同的方法集創建一個Interface對象。 
4)、 剔除所有針對構造器顯式檢查。因為我們使用是鴨式辨型,所以對象的類型不再重要。 
5)、 以Interface.ensureImplements取代原來的構造器檢查。

示例 
假設你要創建一個類,它可以將一些自動化測試結果轉化為適于在網頁上查看的格式。該類的構造器以一個TestResult類的實例為參數。它會應客戶的請求對這個TestResult對象所封裝的數據進行格式化,然后輸出。 
原始定義:

 

 var ResultFormatter =function(resultsObject){    if(!(resultsObject instanceof TestResult)){      throw newError("ResultsFormatter:constructor requires an instance of TestResult asan argument.")    }    this.resultsObject = resultsObject;  }  ResultFormatter.prototype.renderResults =function(){    var dateOfTest = this.resultsObject.getDate();    var resultsArray =this.resultsObject.getResults();    var resultsContainer =document.createElement('div');    var resultsHeader =document.createElement("h3");    resultsHeader.innerHTML = "TestResults from "+dateOfTest.toUTCString();    resultsContainer.appendChild(resultsHeader);    var resultList =document.createElement("ul");    resultsContainer.appendChild(resultList);    for(var i=0,len=resultsArray.length;i<len;i++){      var listItem=document.createElement('li');      listItem.innerHTML =resultsArray[i];      resultList.appendChild(listItem);    }    return resultsContainer;  }

該類的構造器會對參數進行檢查,以確保其的確為TestResult類的實例。如果參數達不到要示,構造器將拋出一個錯誤。有了這樣的保證,在編寫renderResults方法時,你就可以認定有getDate和getResults這兩個方法可供使用。實際上這并不能保證所需要的方法得到了實現。TestResult類可能會被修改,致使其不再擁有getDate()方法。在此情況下,構造器中的檢查仍能通過,但renderResults方法卻會失靈。

此外,構造器的這個檢查施加了一些不必要的限制。它不允許使用其他類的實例作為參數,哪怕它們原本可以如愿發揮作用。例如,有一個名為WeatherData在也擁有getDate和getResults這兩個方法。它本來可以被ResultFormatter類用得好好的。但是那個顯式類型檢查會阻止使用WeatherData類的任何實例。 
問題解決辦法是刪除那個使用instanceOf的檢查,并用接口代替它。首先,我們需要創建這個接口:

//ResultSetInterface.var ResultSet =new Interface(“ResultSet”,[‘getDate','getResults']);

上面的這行代碼創建了一個Interface對象的新實例。第一個參數是接口的名稱,第二個參數是一個字符串數組,其中的每個字符串都是一個必需的方法名稱。有了這個接口之后,就可以用接口檢查替代instanceOf檢查了

var ResultFormatter = function(resultsObject){ Interface.ensureImplements(resultsObject,ResultSet); this.resultsObject = resultsObject;}ResultFormatter.prototype.renderResults= function(){ …}

renderResults方法保持不變。而構造器則被改為使用ensureImplements方法而不是instanceof運算符?,F在構造器可以接受WeatherData或其他任何實現所需要方法的類的實例。我們只修改了幾行ResultFormatter類代碼,就讓那個檢查變得更準確,而且更寬容。

5、依賴于接口的設計模式

  • 工廠模式
  • 組合模式
  • 裝飾模式
  • 命令模式

以上就是JavaScript設計模式中接口的實現相關介紹,希望對大家的學習有所幫助。



注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲人成在线电影| 国产一区二区三区久久精品| 国产精品电影观看| 午夜精品视频网站| 欧美激情2020午夜免费观看| 欧美亚洲国产视频小说| 精品久久久久久久久久久久久| 欧美亚洲另类在线| 亚洲欧美制服中文字幕| 91免费的视频在线播放| 国产精品网站视频| 久久久久久综合网天天| 精品久久久久久久久中文字幕| 欧美午夜激情在线| 久久久在线视频| 欧美怡春院一区二区三区| 亚洲高清一二三区| 亚洲精品成人久久电影| 精品久久久久久久久久| 亚洲最大的av网站| 亚洲欧美日韩中文视频| 孩xxxx性bbbb欧美| 国产精品高潮粉嫩av| 欧美激情18p| 日韩欧美在线看| 欧美在线一区二区视频| 欧美午夜视频在线观看| 91av视频在线| 欧美日韩在线观看视频小说| 在线日韩中文字幕| 91日韩在线播放| 久久久久久久久久国产精品| 高清视频欧美一级| 久久久亚洲成人| 九九九久久国产免费| 91九色综合久久| 国产精品久久久久久亚洲影视| 日韩在线播放一区| 国产精品扒开腿做爽爽爽视频| 国产亚洲激情视频在线| 97色伦亚洲国产| 成人国产精品久久久| 国产精品人人做人人爽| 国产成人中文字幕| 国产a∨精品一区二区三区不卡| 久久偷看各类女兵18女厕嘘嘘| 免费av一区二区| 狠狠色狠狠色综合日日小说| 8090成年在线看片午夜| 日本亚洲欧美三级| 亚洲一区二区久久久久久久| 亚洲第一福利网| 中日韩美女免费视频网站在线观看| 亚洲精品综合久久中文字幕| 亚洲一区二区在线播放| 91精品国产乱码久久久久久久久| 欧美大片第1页| 午夜精品理论片| 一道本无吗dⅴd在线播放一区| 亚洲国产成人久久综合| 欧美精品aaa| 精品久久久91| 琪琪亚洲精品午夜在线| 亚洲欧美综合区自拍另类| 久久手机精品视频| 日韩免费电影在线观看| 成人黄色片网站| 国产成人精品综合久久久| 日本乱人伦a精品| 中文字幕成人精品久久不卡| 欧美怡红院视频一区二区三区| 欧美视频在线看| 国产偷国产偷亚洲清高网站| 欧美在线一区二区三区四| 国内精品久久久久久中文字幕| 精品国产一区二区三区四区在线观看| 亚洲社区在线观看| 欧美大片网站在线观看| 日韩在线视频观看正片免费网站| 国产精品欧美久久久| 国产一区二区三区直播精品电影| 日韩中文字在线| 69av成年福利视频| 亚洲成人免费在线视频| 成人啪啪免费看| 2019亚洲日韩新视频| 亚洲一级片在线看| 亚洲一二三在线| 亚洲视频第一页| 国产精品久久久久久婷婷天堂| 国产精品亚洲综合天堂夜夜| 久久久久久久久久国产精品| 国产福利精品视频| 亚洲深夜福利视频| 国产免费观看久久黄| 日韩精品一区二区三区第95| 久久久天堂国产精品女人| 国产精品高潮粉嫩av| 成人午夜一级二级三级| 亚洲丝袜一区在线| 亚洲欧美另类国产| 国产欧美精品在线| 亚洲理论电影网| 久久久国产一区二区三区| 欧美华人在线视频| 欧美大成色www永久网站婷| 日韩免费在线免费观看| 9.1国产丝袜在线观看| 国产亚洲精品va在线观看| 亚洲护士老师的毛茸茸最新章节| 欧美wwwwww| 激情亚洲一区二区三区四区| 三级精品视频久久久久| 久久久91精品国产| 超碰97人人做人人爱少妇| 亚洲影院色无极综合| 欧美精品九九久久| 久久精品电影网| 久久久久亚洲精品国产| 粗暴蹂躏中文一区二区三区| 亚洲深夜福利在线| 久久久爽爽爽美女图片| 国产精品露脸自拍| 国产日韩中文在线| 97久久精品人人澡人人爽缅北| 久久精品色欧美aⅴ一区二区| 少妇精69xxtheporn| 亚洲理论片在线观看| 97视频免费在线看| 成人黄色大片在线免费观看| 亚洲美女精品久久| 国产精品久久久久久久久久ktv| 丝袜美腿亚洲一区二区| 亚洲色图第三页| 亚洲精品国精品久久99热| 久久免费在线观看| 国产精品三级网站| 亚洲国产另类 国产精品国产免费| 中文字幕视频一区二区在线有码| 92看片淫黄大片看国产片| www国产亚洲精品久久网站| 欧美综合国产精品久久丁香| 国产成人精品av| 欧美天堂在线观看| 91精品国产91久久久久| 97视频在线观看亚洲| 久久精品视频在线| 2018中文字幕一区二区三区| 91久久综合亚洲鲁鲁五月天| 久久精品男人天堂| 亚洲精品98久久久久久中文字幕| 一区二区三区黄色| 97国产一区二区精品久久呦| 91免费的视频在线播放| 在线电影中文日韩| 中文.日本.精品| 中文字幕综合在线| 色哟哟网站入口亚洲精品| 国外日韩电影在线观看| 午夜精品久久久久久久男人的天堂| 精品久久久久久| 日韩av电影在线免费播放| 久久99久久99精品中文字幕| 欧美性xxxx极品hd欧美风情|