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

首頁 > 編程 > JavaScript > 正文

學習JavaScript設計模式(接口)

2019-11-20 11:09:24
字體:
來源:轉載
供稿:網友

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設計模式中接口的實現相關介紹,希望對大家的學習有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品国产三级国产aⅴ9色| 在线成人中文字幕| 青青草原一区二区| 91精品国产高清自在线| 久久久精品日本| 国产在线视频91| 亚洲www在线观看| 亚洲a级在线播放观看| 在线视频日本亚洲性| 法国裸体一区二区| 国产一区二区三区毛片| 久久99精品久久久久久噜噜| 久久久这里只有精品视频| 亚洲男人的天堂在线播放| 91久久久久久久久| 国产性色av一区二区| 久久久久成人网| 欧美日韩国产一区中文午夜| 怡红院精品视频| 欧美日韩国产91| 日韩av网站导航| 欧美又大又粗又长| 欧美日韩ab片| 国内揄拍国内精品少妇国语| 在线观看国产精品日韩av| 日韩在线视频一区| 国产日韩在线免费| 中文字幕精品在线| 成人性生交大片免费看小说| 久久精品在线视频| 欧美影院在线播放| 久久久久女教师免费一区| 在线视频日韩精品| 亚洲精品v天堂中文字幕| 久久黄色av网站| 国产一区二区日韩精品欧美精品| 欧美国产精品日韩| 91久久国产精品91久久性色| 亚洲国产一区二区三区在线观看| 91高潮在线观看| 精品magnet| 疯狂做受xxxx高潮欧美日本| 久久香蕉精品香蕉| 国外成人性视频| 黄色成人在线免费| 亚洲精品美女久久| 中文字幕亚洲一区二区三区| 538国产精品一区二区免费视频| 日韩最新在线视频| 欧美日韩精品在线| 久久九九国产精品怡红院| 奇米一区二区三区四区久久| 中文字幕在线视频日韩| 久久九九有精品国产23| 国产精品最新在线观看| 国产精品影片在线观看| 最好看的2019的中文字幕视频| 成人午夜在线观看| 欧美日韩在线一区| 国产成一区二区| 日韩精品中文字幕久久臀| 中文字幕一精品亚洲无线一区| 一区二区三区视频免费在线观看| 精品国内产的精品视频在线观看| 久久精品国产清自在天天线| 欧美激情亚洲综合一区| 日韩av一区二区在线| www高清在线视频日韩欧美| 亚洲自拍高清视频网站| 国产一区二区三区免费视频| 国产精品成人播放| 国产精品第一区| 亚洲一区二区三区777| 最近2019年好看中文字幕视频| 欧美激情视频在线| 亚洲日本欧美中文幕| 国产精品高潮呻吟视频| 91视频国产高清| 青草青草久热精品视频在线观看| 亚洲free性xxxx护士hd| 亚洲女人天堂成人av在线| 国产精品pans私拍| 亚洲国产女人aaa毛片在线| 国产精品一区av| 欧美日韩在线另类| 欧美成人一区二区三区电影| 自拍亚洲一区欧美另类| 日韩福利在线播放| 亚洲精品一区二区在线| 日韩欧美亚洲国产一区| 国产国语videosex另类| 欧美超级免费视 在线| 日韩欧美成人免费视频| 欧美午夜女人视频在线| 欧美日韩亚洲视频一区| 欧美成人黑人xx视频免费观看| 亚洲国产精品久久久久秋霞蜜臀| 国产精品色悠悠| 久久久久国产精品www| 欧美久久久精品| 疯狂蹂躏欧美一区二区精品| 精品一区二区三区四区在线| 久久免费视频在线| 欧美网站在线观看| 精品一区电影国产| 久久精品2019中文字幕| 色噜噜国产精品视频一区二区| 欧美成人四级hd版| 青草青草久热精品视频在线观看| 日韩精品视频三区| 成人国产亚洲精品a区天堂华泰| 久久精品99久久久久久久久| 国产亚洲一区二区在线| 国产精品盗摄久久久| 欧美国产日本在线| 国产成人精品久久亚洲高清不卡| 久热精品在线视频| 久久6免费高清热精品| 热久久美女精品天天吊色| 日韩精品欧美国产精品忘忧草| 日本精品一区二区三区在线| 蜜臀久久99精品久久久久久宅男| 国产欧美日韩中文字幕| 成人黄色在线播放| 国产在线98福利播放视频| 久久韩国免费视频| 精品久久香蕉国产线看观看亚洲| 国产精品一二三在线| 日韩av在线直播| 2020久久国产精品| 欧美孕妇性xx| 亚洲热线99精品视频| 一区二区三区回区在观看免费视频| 国内精品400部情侣激情| 日韩av三级在线观看| 久久人91精品久久久久久不卡| 欧美在线亚洲一区| 91色中文字幕| 国产99久久精品一区二区永久免费| 欧美大胆a视频| 成人免费福利在线| 亚洲欧美第一页| 亚洲第一区第二区| 精品国产91久久久久久老师| 国产精品狼人色视频一区| 国产成人精品国内自产拍免费看| 日韩的一区二区| 视频直播国产精品| 夜色77av精品影院| 日韩av在线影院| 亚洲第一视频在线观看| 日本成人黄色片| 中文字幕欧美精品在线| 狠狠色噜噜狠狠狠狠97| www.99久久热国产日韩欧美.com| 日韩精品久久久久| 国产一区二区三区中文| 亚洲一区美女视频在线观看免费| 91tv亚洲精品香蕉国产一区7ujn| 亚洲日韩中文字幕在线播放| 美女久久久久久久久久久| 77777亚洲午夜久久多人| 欧美裸体xxxx| 精品视频久久久|