【js】接口實現代碼
一、什麽是接口
接口是面向對象JavaScript程序員的工具箱中最有用的工具之一。在設計模式中提出的可重用的面向對象設計的原則之一就是“針對接口編程而不是實現編程”,即我們所說的面向接口編程,這個概念的重要性可見一斑。但問題在於,在JavaScript的世界中,沒有內置的創建或實現接口的方法,也沒有可以判斷一個對象是否實現了與另一個對象相同的一套方法,這使得對象之間很難互換使用,好在JavaScript擁有出色的靈活性,這使得模擬傳統面向對象的接口,添加這些特性並非難事。接口提供了一種用以說明一個對象應該具有哪些方法的手段,盡管它可以表明這些方法的含義,但是卻不包含具體實現。有了這個工具,就能按對象提供的特性對它們進行分組。例如,假如A和B以及接口I,即便A對象和B對象有極大的差異,只要他們都實現了I接口,那麽在A.I(B)方法中就可以互換使用A和B,如B.I(A)。還可以使用接口開發不同的類的共同性。如果把原本要求以一個特定的類為參數的函數改為要求以一個特定的接口為參數的函數,那麽所有實現了該接口的對象都可以作為參數傳遞給它,這樣一來,彼此不相關的對象也可以被相同地對待。
既定的接口具有自我描述性,並能夠促進代碼的重用性,接口可以提供一種信息,告訴外部一個類需要實現哪些方法。還有助於穩定不同類之間的通信方式,減少了繼承兩個對象的過程中出現的問題。這對於調試也是有幫助的,在JavaScript這種弱類型語言中,類型不匹配很難追蹤,使用接口時,如果出現了問題,會有更明確的錯誤提示信息。當然接口並非完全沒有缺點,如果大量使用接口會一定程度上弱化其作為弱類型語言的靈活性,另一方面,JavaScript並沒有對接口的內置的支持,只是對傳統的面向對象的接口進行模擬,這會使本身較為靈活的JavaScript變得更加難以駕馭。此外,任何實現接口的方式都會對性能造成影響,某種程度上歸咎於額外的方法調用開銷。接口使用的最大的問題在於,JavaScript不像是其他的強類型語言,如果不遵守接口的約定,就會編譯失敗,其靈活性可以有效地避開上述問題,如果是在協同開發的環境下,其接口很有可能被破壞而不會產生任何錯誤,也就是不可控性。
在面向對象的語言中,使用接口的方式大體相似。接口中包含的信息說明了類需要實現的方法以及這些方法的簽名。類的定義必須明確地聲明它們實現了這些接口,否則是不會編譯通過的。顯然在JavaScript中我們不能如法炮制,因為不存在interface和implement關鍵字,也不會在運行時對接口是否遵循約定進行檢查,但是我們可以通過輔助方法和顯式地檢查模仿出其大部分特性。
三、在JavaScript中模仿接口在JavaScript中模仿接口主要有三種方式:通過註釋、屬性檢查和鴨式辯型法,以上三種方式有效結合,就會產生類似接口的效果。
註釋是一種比較直觀地把與接口相關的關鍵字(如interface、implement等)與JavaScript代碼一同放在註釋中來模擬接口,這是最簡單的方法,但是效果最差。
/*******************************************************************************************************************************************************************************************************************/
/**
* 創建接口對象
* @param name 接口名
* @param methods 接口方法
*/
var
Interface =
function
(name,methods){
if
(arguments.length != 2){
throw
new
Error(
‘必須輸入兩個參數,當前個數‘
+arguments.length);
}
this
.name=name;
this
.methods=[];
for
(
var
i=0, len=methods.length; i<len; i++){
if
(
typeof
methods[i] !==
‘string‘
){
throw
new
Error(
‘方法名參數必須為string‘
);
}
this
.methods.push(methods[i]);
}
};
/**
* 接口實現
* @param object1 實現接口對象
* @param object2 對應接口
* @return 實現錯誤拋出異常
*/
Interface.ensureImplements =
function
(object){
if
(arguments.length < 2){
throw
new
Error(
‘必須輸入兩個參數,當前個數‘
+ arguments.length);
}
for
(
var
i=1, len=arguments.length; i < len; i++){
var
interface = arguments[i];
if
(interface.constructor != Interface){
throw
new
Error(
"請實現接口"
);
}
for
(
var
j = 0, methodsLen = interface.methods.length; j < methodsLen; j++){
var
method = interface.methods[j];
if
(!object[method] ||
typeof
object[method] !==
‘function‘
){
throw
new
Error(
"接口名:"
+interface.name+
"方法名:"
+method+
"沒找到"
);
}
};
}
}
var
DynamicMap =
new
Interface(
‘DynamicMap‘
,[
‘centerOnPoint‘
,
‘zoom‘
,
‘draw‘
]);
/**
* 執行方法
* @param 函數方法
* @return 執行結果
*/
function
displayRoute(mapInstance){
Interface.ensureImplements(mapInstance,DynamicMap);
//實現接口
/**
* 調用
*/
mapInstance.centerOnPoint(12,34);
mapInstance.zoom(5);
mapInstance.draw();
}
/**
* 函數方法
* @type 實現接口方法
*/
var
a={
centerOnPoint:
function
(x,y){
console.log(x*y);
},
zoom:
function
(x){
console.log(x);
},
draw:
function
(){
console.log(
"x*y"
);
}
}
displayRoute(a);
【js】接口實現代碼