JavaScript实现接口的三种经典方式

时间:2019-04-19
本文章向大家介绍JavaScript实现接口的三种经典方式,主要包括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();