JavaScript實現接口的三種經典方式


接口:提供一種說明一個對象應該有哪些方法的手段

 

JavaScript中有三種方式實現接口:

(1)注釋描述接口

(2)屬性檢測接口

(3)鴨式辨型接口

 

1、注釋描述接口:不推薦

優點:易於實現,不需要額外的類或函數。

缺點:純文檔約束,程序不能檢查實現接口的對象是否實現了所有接口方法

 1 /**
 2  * interface Composite{
 3  *         function a();
 4  *         function b();
 5  * }
 6  */
 7 // CompositeImpl implements Composite
 8 var CompositeImpl = function(){
 9     //業務邏輯
10 };
11 CompositeImpl.prototype.a = function(){
12     //業務邏輯
13 };
14 CompositeImpl.prototype.b = function(){
15     //業務邏輯
16 };

 

2、屬性檢測接口:不推薦

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

優點:能夠檢查實現了哪些接口

缺點:並未確保類真正實現了自稱實現的接口。你只知道它是否說自己實現了接口。

 

 1 var interfacesImpl = function(){
 2     //在實現類內部用一個數組保存要實現的方法名
 3     //通常這個屬性名是團隊中規定好的
 4     //聲明自己實現了這兩個方法,但實際上並不一定
 5     this.implementsInterfaces = ["Composite","FormItem"];
 6 };
 7 
 8 //專門為這個實現對象寫一個檢測函數,傳入實例對象,用於檢查實例對象是否實現了所有接口
 9 function checkImplements(obj){
10     //調用檢查方法 obj是否實現了兩個接口,如果沒有都實現則拋出異常
11     if(!isImplements(obj,"Composite","FormItem")){
12         throw new Error("接口沒有全部實現!");
13     }
14     //obj是要檢查的對象
15     function isImplements(obj){
16         //傳入的第0個參數是要檢查的對象,所以從1開始檢查
17         for(var i=1; i<arguments.length; i++){
18             //接收接口中每個接口的名字
19             var interfaceName = arguments[i];
20             //默認未實現該接口
21             var foundFlag = false;
22             //循環查詢傳入實例對象的實現接口數組,檢查是否全部實現
23             for(var j=0; j<obj.implementsInterfaces.length; j++){
24                 //如果實現了這個接口,就修改標記並跳出
25                 //debugger
26                 if(obj.implementsInterfaces[j] == interfaceName){
27                     foundFlag = true;
28                     break;
29                 }
30             }
31             //如果遍歷實現接口數組之后沒找到,返回false
32             if(!foundFlag){
33                 return false;
34             }
35         }
36         return true;
37     }
38 }
39 
40 //使用實例對象並檢測
41 var o = new interfacesImpl();
42 checkImplements(o);

 

3、鴨式辨型法:推薦

背后的觀點:如果對象具有與接口定義的方法同名的所有方法,那么久可以認為它實現了這個接口。

 1 /**
 2  * 接口類
 3  *
 4  * @param {String} name  接口的名字
 5  * @param {Array} methods   要實現方法名稱的數組
 6  */
 7 var Interface = function (name, methods) {
 8     //判斷參數個數
 9     if(arguments.length !== 2){
10         throw new Error("接口構造器參數必須是兩個!");
11     }
12     this.name = name;
13     this.methods = [];
14     for(var i=0; i<methods.length; i++){
15         if(typeof methods[i] !== "string"){
16             throw new Error("接口實現的函數名稱必須是字符串!");
17         }
18         this.methods.push(methods[i]);
19     }
20 }
21 
22 //實例化接口對象---傳入接口名和要實現的方法數組
23 var CompositeInterface = new Interface("CompositeInterface",["add","remove"]);
24 var FormItemInterface = new Interface("FormItemInterface",["update","select"]);
25 
26 //實現接口的類
27 var CompositeImpl = function(){
28 
29 }
30 
31 //實現接口的方法
32 CompositeImpl.prototype.add = function(obj){
33     //...
34 }
35 CompositeImpl.prototype.remove = function(obj){
36     //...
37 }
38 CompositeImpl.prototype.select = function(obj){
39     //...
40 }
41 //在這里少實現一個方法,下面檢查是否全部實現了接口
42 // CompositeImpl.prototype.update = function(obj){
43 //     //...
44 // }
45 
46 //實例化 實現接口的對象
47 var c = new CompositeImpl();
48 
49 //檢驗接口里的方法是否全部實現,如果不通過則拋出異常
50 Interface.ensureImplements = function(obj){
51     //如果接收到參數小於2,說明異常
52     if(arguments.length < 2){
53         throw new Error("接口檢查方法的參數必須多余兩個!");
54     }
55     //接口實現檢查
56     for(var i=0,len = arguments.length; i<len; i++){
57         //獲取當前接口
58         var instanceInterface = arguments[i];
59         //判斷接收到的是不是接口的對象,如果不是則拋出異常
60         if(instanceInterface.constructor !== Interface){
61             throw new Error("接口檢測函數必須傳入接口對象!");
62         }
63         //檢查實例化接口的對象是不是實現了接口里的所有方法
64         for(var j=0; j<instanceInterface.methods.length; j++){
65             //接收到的字符串方法
66             var methodName = instanceInterface.methods[j];
67             //如果obj里面沒有methodsName這個方法,或者有這個屬性但是不是函數,就拋出異常
68             if(!obj[methodName] || typeof obj[methodName] !== "function"){
69                 throw new Error("接口方法" + methodName + "沒有實現!");
70             }
71         }
72     }
73 }
74 
75 //傳入要檢查的類,和要實現的所有接口對象
76 Interface.ensureImplements(c, CompositeInterface, FormItemInterface);
77 c.add();

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM