av人人干_女狠狠噜天天噜日日噜_国产精品一区二区免费_亚洲国语自产一区第二页_免费av观看_已婚少妇露脸日出白浆_国产精品探花视频_久久国产精品2020免费_国产精品好好热av在线观看_亚洲另类春色校园小说

網(wǎng)站建設(shè)知識

我們將想法與焦點與您一起共享

當前位置:深圳網(wǎng)站建設(shè) > 網(wǎng)站建設(shè)知識> 深圳網(wǎng)站建設(shè)|淺談JavaScript中的接口

深圳網(wǎng)站建設(shè)|淺談JavaScript中的接口

2017/6/6 8:43:13 獨占網(wǎng)絡(luò) 網(wǎng)站建設(shè)知識
一、什么是接口

接口是面向?qū)ο驤avaScript程序員的工具箱中有用的工具之一。在設(shè)計模式中提出的可重用的面向?qū)ο笤O(shè)計的原則之一就是“針對接口編程而不是實現(xiàn)編程”,即我們所說的面向接口編程,這個概念的重要性可見一斑。但問題在于,在JavaScript的世界中,沒有內(nèi)置的創(chuàng)建或?qū)崿F(xiàn)接口的方法,也沒有可以判斷一個對象是否實現(xiàn)了與另一個對象相同的一套方法,這使得對象之間很難互換使用,好在JavaScript擁有出色的靈活性,這使得模擬傳統(tǒng)面向?qū)ο蟮慕涌?,添加這些特性并非難事。接口提供了一種用以說明一個對象應(yīng)該具有哪些方法的手段,盡管它可以表明這些方法的含義,但是卻不包含具體實現(xiàn)。有了這個工具,就能按對象提供的特性對它們進行分組。例如,假如A和B以及接口I,即便A對象和B對象有極大的差異,只要他們都實現(xiàn)了I接口,那么在A.I(B)方法中就可以互換使用A和B,如B.I(A)。還可以使用接口開發(fā)不同的類的共同性。如果把原本要求以一個特定的類為參數(shù)的函數(shù)改為要求以一個特定的接口為參數(shù)的函數(shù),那么所有實現(xiàn)了該接口的對象都可以作為參數(shù)傳遞給它,這樣一來,彼此不相關(guān)的對象也可以被相同地對待。

二、接口的利與弊

既定的接口具有自我描述性,并能夠促進代碼的重用性,接口可以提供一種信息,告訴外部一個類需要實現(xiàn)哪些方法。還有助于穩(wěn)定不同類之間的通信方式,減少了繼承兩個對象的過程中出現(xiàn)的問題。這對于調(diào)試也是有幫助的,在JavaScript這種弱類型語言中,類型不匹配很難追蹤,使用接口時,如果出現(xiàn)了問題,會有更明確的錯誤提示信息。當然接口并非完全沒有缺點,如果大量使用接口會一定程度上弱化其作為弱類型語言的靈活性,另一方面,JavaScript并沒有對接口的內(nèi)置的支持,只是對傳統(tǒng)的面向?qū)ο蟮慕涌谶M行模擬,這會使本身較為靈活的JavaScript變得更加難以駕馭。此外,任何實現(xiàn)接口的方式都會對性能造成影響,某種程度上歸咎于額外的方法調(diào)用開銷。接口使用的大的問題在于,JavaScript不像是其他的強類型語言,如果不遵守接口的約定,就會編譯失敗,其靈活性可以有效地避開上述問題,如果是在協(xié)同開發(fā)的環(huán)境下,其接口很有可能被破壞而不會產(chǎn)生任何錯誤,也就是不可控性。

在面向?qū)ο蟮恼Z言中,使用接口的方式大體相似。接口中包含的信息說明了類需要實現(xiàn)的方法以及這些方法的簽名。類的定義必須明確地聲明它們實現(xiàn)了這些接口,否則是不會編譯通過的。顯然在JavaScript中我們不能如法炮制,因為不存在interface和implement關(guān)鍵字,也不會在運行時對接口是否遵循約定進行檢查,但是我們可以通過輔助方法和顯式地檢查模仿出其大部分特性。

三、在JavaScript中模仿接口

在JavaScript中模仿接口主要有三種方式:通過注釋、屬性檢查和鴨式辯型法,以上三種方式有效結(jié)合,就會產(chǎn)生類似接口的效果。
注釋是一種比較直觀地把與接口相關(guān)的關(guān)鍵字(如interface、implement等)與JavaScript代碼一同放在注釋中來模擬接口,這是簡單的方法,但是效果差。代碼如下:

JavaScript

//以注釋的形式模仿描述接口
/*
interface Composite{
    function add(child);
    function remove(child);
    function getName(index);
}

interface FormItem{
    function save();
}
*/


//以注釋的形式模仿使用接口關(guān)鍵字
var CompositeForm =function(id , method,action) { //implements Composite , FormItem
    // do something
}
//模擬實現(xiàn)具體的接口方法 此處實現(xiàn)Composite接口
CompositeForm.prototype.Add=function(){
    // do something
}

CompositeForm.prototype.remove=function(){
    // do something
}

CompositeForm.prototype.getName=function(){
    // do something
}

//模擬實現(xiàn)具體的接口方法 此處實現(xiàn)FormItem接口
Composite.prototype.save=function(){
    // do something

這種方式其實并不是很好,因為這種模仿還只停留在文檔規(guī)范的范疇,開發(fā)人員是否會嚴格遵守該約定有待考量,對接口的遵守完全依靠開發(fā)人員的自覺性。另外,這種方式并不會去檢查某個函數(shù)是否真正地實現(xiàn)了我們約定的“接口”。盡管如此,這種方式也有優(yōu)點,它易于實現(xiàn)而不需要額外的類或者函數(shù),可以提高代碼的可重用性,因為類實現(xiàn)的接口都有注釋說明。這種方式不會影響到文件占用的空間或執(zhí)行速度,因為注釋的代碼可以在部署的時候輕松剔除。但是由于不會提供錯誤消息,它對測試和調(diào)試沒什么幫助。下面的一種方式會對是否實現(xiàn)接口進行檢查,代碼如下:

JavaScript

//以注釋的形式模仿使用接口關(guān)鍵字
var CompositeForm =function(id , method,action) { //implements Composite , FormItem
    // do something
    this.implementsinterfaces=['Composite','FormItem']; //顯式地把接口放在implementsinterfaces中
}


//檢查接口是否實現(xiàn)
function implements(Object){
    for(var i=0 ;i< arguments.length;i++){
        var interfaceName=arguments[i];
        var interfaceFound=false;
        for(var j=0;j<Object.implementsinterfaces.length;j++){
            if(Object.implementsinterfaces[j]==interfaceName){
                interfaceFound=true;
                break;
            }
        }
        if(!interfaceFound){
            return false;
        }else{
            return true;
        }
    }
}


function AddForm(formInstance){
    if(!implements(formInstance,'Composite','FormItem')){ 
        throw new Error('Object does not implements required interface!');
    }

上述代碼是在方式一的基礎(chǔ)上進行完善,在這個例子中,CompositeForm宣稱自己實現(xiàn)了Composite和FormItem這兩個接口,其做法是把這兩個接口的名稱加入一個implementsinterfaces的數(shù)組。顯式地聲明自己支持什么接口。任何一個要求其參數(shù)屬性為特定類型的函數(shù)都可以對這個屬性進行檢查,并在所需要的接口未在聲明之中時拋出錯誤。這種方式相對于上一種方式,多了一個強制性的類型檢查。但是這種方法的缺點在于它并未保證類真正地實現(xiàn)了自稱實現(xiàn)的接口,只是知道它聲明自己實現(xiàn)了這些接口。其實類是否聲明自己支持哪些接口并不重要,只要它具有這些接口中的方法就行。鴨式辯型(像鴨子一樣走路并且嘎嘎叫的就是鴨子)正是基于這樣的認識,它把對象實現(xiàn)的方法集作為判斷它是不是某個類的實例的標準。這種技術(shù)在檢查一個類是否實現(xiàn)了某個接口時也可以大顯身手。這種方法的背后觀點很簡單:如果對象具有與接口定義的方法同名的所有方法,那么就可以認為它實現(xiàn)了這個接口。可以使用一個輔助函數(shù)來確保對象具有所有必需的方法,代碼如下:

JavaScript

//interface
var Composite =new Interface('Composite',['add','remove','getName']);
var FormItem=new Interface('FormItem',['save']);

//class
var Composite=function(id,method,action){
    
}

//Common Method
function AddForm(formInstance){
    ensureImplements(formInstance,Composite,FormItem);
    //如果該函數(shù)沒有實現(xiàn)指定的接口,這個函數(shù)將會報錯

與另外兩種方式不同,這種方式無需注釋,其余的各個方面都是可以強制實施的。EnsureImplements函數(shù)需要至少兩個參數(shù)。個參數(shù)是想要檢查的對象,其余的參數(shù)是被檢查對象的接口。該函數(shù)檢查器個參數(shù)代表的對象是否實現(xiàn)了那些接口所聲明的方法,如果漏掉了任何一個,就會拋錯,其中會包含被遺漏的方法的有效信息。這種方式不具備自我描述性,需要一個輔助類和輔助函數(shù)來幫助實現(xiàn)接口檢查,而且它只關(guān)心方法名稱,并不檢查參數(shù)的名稱、數(shù)目或類型。

四、Interface類

在下面的代碼中,對Interface類的所有方法的參數(shù)都進行了嚴格的控制,如果參數(shù)沒有驗證通過,那么就會拋出異常。加入這種檢查的目的就是,如果在執(zhí)行過程中沒有拋出異常,那么就可以肯定接口得到了正確的聲明和實現(xiàn)。

JavaScript

var Interface = function(name ,methods){
    if(arguments.length!=2){
        throw new Error('2 arguments required!');
    }
    this.name=name;
    this.methods=[];
    for(var i=0;len=methods.length;i<len;i++){
        if(typeof(methods[i]!=='String')){
            throw new Error('method name must be String!');
        }
        this.methods.push(methods[i]);
    }
}


Interface.ensureImplements=function(object){
    if(arguments.length<2){
        throw new Error('2 arguments required at least!');
    }
    for(var i=0;len=arguments.length;i<len;i++){
        var interface=arguments[i];
        if(interface.constructor!==Interface){
            throw new Error('instance must be Interface!');
        }
        for(var j=0;methodLength=interface.methods.length;j<methodLength;j++){
            var method=interface.methods[j];
            if(!object[method]||typeof(object[method])=='function')){
                throw new Error('object does not implements method!');
            }    
        }
    }

其實多數(shù)情況下,接口并不是經(jīng)常被使用的,嚴格的類型檢查并不總是明智的。但是在設(shè)計復雜的系統(tǒng)的時候,接口的作用就體現(xiàn)出來了,這看似降低了靈活性,卻同時也降低了耦合性,提高了代碼的重用性。這在大型系統(tǒng)中是比較有優(yōu)勢的。在下面的例子中,聲明了一個displayRoute方法,要求其參數(shù)具有三個特定的方法,通過Interface對象和ensureImplements方法來保證這三個方法的實現(xiàn),否則將會拋出錯誤。

JavaScript

//聲明一個接口,描述該接口包含的方法
 var DynamicMap=new Interface{'DynamicMap',['centerOnPoint','zoom','draw']};

 //聲明一個displayRoute方法
 function displayRoute(mapInstance){
    //檢驗該方法的map
    //檢驗該方法的mapInsstance是否實現(xiàn)了DynamicMap接口,如果未實現(xiàn)則會拋出
    Interface.ensureImplements(mapInstance,DynamicMap);
    //如果實現(xiàn)了則正常執(zhí)行
    mapInstance.centerOnPoint(12,22);
    mapInstance.zoom(5);
    mapInstance.draw();
 } 
下面的例子會將一些數(shù)據(jù)以網(wǎng)頁的形式展現(xiàn)出來,這個類的構(gòu)造器以一個TestResult的實例作為參數(shù)。該類會對TestResult對象所包含的數(shù)據(jù)進行格式化(Format)后輸出,代碼如下:

JavaScript

var ResultFormatter=function(resultObject){
     //對resultObject進行檢查,保證是TestResult的實例
     if(!(resultObject instanceof TestResult)){
         throw new Error('arguments error!');
     }
     this.resultObject=resultObject;
 }

 ResultFormatter.prototype.renderResult=function(){
     var dateOfTest=this.resultObject.getData();
     var resultArray=this.resultObject.getResults();
     var resultContainer=document.createElement('div');
     var resultHeader=document.createElement('h3');
     resultHeader.innerHTML='Test Result from '+dateOfTest.toUTCString();
     resultContainer.appendChild(resultHeader);

     var resultList=document.createElement('ul');
     resultContainer.appendChild(resultList);

     for(var i=0;len=resultArray.length;i<len;i++){
         var listItem=document.createElement('li');
         listItem.innerHTML=resultArray[i];
         resultList.appendChild('listItem');
     }
     return resultContainer;
 } 
該類的構(gòu)造器會對參數(shù)進行檢查,以確保其的確為TestResult的類的實例。如果參數(shù)達不到要求,構(gòu)造器將會拋出一個錯誤。有了這樣的保證,在編寫renderResult方法的時候,就可以認定有g(shù)etData和getResult兩個方法。但是,構(gòu)造函數(shù)中,只對參數(shù)的類型進行了檢查,實際上這并不能保證所需要的方法都得到了實現(xiàn)。TestResult類會被修改,致使其失去這兩個方法,但是構(gòu)造器中的檢查依舊會通過,只是renderResult方法不再有效。
此外,構(gòu)造器中的這個檢查施加了一些不必要的限制。它不允許使用其他的類的實例作為參數(shù),否則會直接拋錯,但是問題來了,如果有另一個類也包含并實現(xiàn)了getData和getResult方法,它本來可以被ResultFormatter使用,卻因為這個限制而無用武之地。
解決問題的辦法就是刪除構(gòu)造器中的校驗,并使用接口代替。我們采用這個方案對代碼進行優(yōu)化:

JavaScript

//接口的聲明
var resultSet =new Interface('ResultSet',['getData','getResult']);

//修改后的方案
 var ResultFormatter =function(resultObject){
     Interface.ensureImplements(resultObject,resultSet);
     this.resultObject=resultObject;
 } 
上述代碼中,renderResult方法保持不變,而構(gòu)造器卻采用的ensureImplements方法,而不是typeof運算符?,F(xiàn)在的這個構(gòu)造器可以接受任何符合接口的類的實例了。

五、依賴于接口的設(shè)計模式

<1>工廠模式:對象工廠所創(chuàng)建的具體對象會因具體情況而不同。使用接口可以確保所創(chuàng)建的這些對象可以互換使用,也就是說對象工廠可以保證其生產(chǎn)出來的對象都實現(xiàn)了必需的方法;
<2>組合模式:如果不使用接口就不可能使用這個模式,其中心思想是可以將對象群體與其組成對象同等對待。這是通過接口來做到的。如果不進行鴨式辯型或類型檢查,那么組合模式就會失去大部分意義;
<3>裝飾者模式:裝飾者通過透明地為另一個對象提供包裝而發(fā)揮作用。這是通過實現(xiàn)與另外那個對象完全一致的接口實現(xiàn)的。對于外界而言,一個裝飾者和它所包裝的對象看不出有什么區(qū)別,所以使用Interface來確保所創(chuàng)建的裝飾者實現(xiàn)了必需的方法;

<4>命令模式:代碼中所有的命令對象都有實現(xiàn)同一批方法(如run、ecxute、do等)通過使用接口,未執(zhí)行這些命令對象而創(chuàng)建的類可以不必知道這些對象具體是什么,只要知道他們都正確地實現(xiàn)了接口即可。借此可以創(chuàng)建出模塊化程度很高的、耦合度很低的API。

    深圳網(wǎng)站建設(shè)www.ykfic.cn

始終專注高端網(wǎng)站建設(shè)服務(wù) 網(wǎng)站建設(shè)案例服務(wù)方案聯(lián)系

聯(lián)系我們

135-3000-5572
151-1257-9390

地址:深圳市龍崗區(qū)橫崗街道力嘉創(chuàng)意文化產(chǎn)業(yè)園338

郵箱:chenmh@sz886.com

我們的優(yōu)勢

12年建站服務(wù)經(jīng)驗自主開發(fā)后臺CMS開發(fā)項目不外包無隱形收費

服務(wù)198家上市企業(yè)服務(wù)行業(yè)龍頭超過70家 營銷型網(wǎng)站建設(shè)完備的項目流程管理體系網(wǎng)頁設(shè)計與網(wǎng)站開發(fā)技術(shù)并重

關(guān)于獨占網(wǎng)絡(luò)

十多年來,憑借對設(shè)計的深刻理解,對互聯(lián)網(wǎng)營銷趨勢的敏銳洞察,獨占網(wǎng)絡(luò)不斷修正服務(wù)導向,完善創(chuàng)作品格,始終注重專業(yè)探索,為所有合作企業(yè)機構(gòu)全力以赴,確保網(wǎng)站的視覺體驗與營銷轉(zhuǎn)化能力。

我們是一群對互聯(lián)網(wǎng)抱有執(zhí)著信念的技術(shù)控。從2012年到現(xiàn)在,公司從未建過強大的營銷團隊,卻憑著作品與服務(wù)不斷保持增長,做到了"桃李不言,下自成蹊。" 我們堅信:每個客戶都是一條渠道,每個案例都是一個廣告,為企業(yè)插上翅膀,助力企業(yè)轉(zhuǎn)型升級,我們已做好準備。

專業(yè)團隊為您提供深圳網(wǎng)站建設(shè)、深圳網(wǎng)站制作、深圳營銷型網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)等服務(wù),深圳建網(wǎng)站就找獨占網(wǎng)絡(luò) | 12年專注網(wǎng)站建設(shè)

深圳市獨占網(wǎng)絡(luò)科技有限公司 |備案號:粵ICP備15007128| Copyright 2025,ALL Rights Reserved www.ykfic.cn | Copyright 2025版權(quán)所有
Hi,Are you ready? 如果您有意向
請于我們?nèi)〉寐?lián)系。

有一個互聯(lián)網(wǎng)項目想和我們談?wù)剢幔?br>您可以填寫右邊的表格,讓我們了解您的項目需求,這是一個良好的開始,我們將會盡快與你取得聯(lián)系。當然也歡迎您給我們寫信或是打電話,讓我們聽到你的聲音!

獨占-整合互聯(lián)網(wǎng)營銷

地址:深圳市龍崗區(qū)橫崗地鐵A出口力嘉創(chuàng)意文化產(chǎn)業(yè)園338
大客戶專線:深圳 13530005572
售前QQ:1447567909
E-mail: sales@sz886.cn

合作意向表
您希望我們?yōu)槟峁┦裁捶?wù)?
主站蜘蛛池模板: 绍兴市| 太仆寺旗| 博客| 铁岭县| 化德县| 孙吴县| 黑龙江省| 镇巴县| 蒙阴县| 布尔津县| 资阳市| 行唐县| 务川| 塔河县| 平遥县| 巴彦淖尔市| 中超| 平利县| 乐至县| 舞钢市| 香港 | 蒙山县| 西藏| 定襄县| 离岛区| 隆昌县| 三门峡市| 额济纳旗| 九寨沟县| 新源县| 黄山市| 南雄市| 平安县| 涿鹿县| 柳河县| 建昌县| 京山县| 铁力市| 马公市| 嘉善县| 内黄县|