接口:提供一种说明一个对象应该有哪些方法的手段

 

JavaScript中有三种方式实现接口:

(1)注释描述接口

(2)属性检测接口

(3)鸭式辨型接口

 

1、注释描述接口:不推荐

优点:程序员有个参考,不需要额外的类或函数。

缺点:纯文档约束,程序不能检查实现接口的对象是否实现了所有接口方法

// CompositeImpl implements Composite
             var CompositeImpl = function() { // 函数自己量
                 this.add = function(obj){
                     
                 };
                 this.remove = function(obj){
                     
                 }
             }
             
             CompositeImpl.prototype.add = function(obj){
                 // do something
             }
             
             CompositeImpl.prototype.remove = function(obj){
                 // do something
             }
             
             CompositeImpl.prototype.update = function(obj){
                 // do something
             }
             var c1 = new CompositeImpl();
             var c2 = new CompositeImpl();

2、属性检测接口:不推荐

第二种方法要更严谨一点。所有类都明确地声明自己实现了哪些接口,那些想与这些类打交道的对象可以针对这些声明进行检查。那些接口自身仍然只是注释,但现在你可以通过检查一个属性得知某个类自称实现了什么接口。

优点:能够检查实现了哪些接口, 耦合性降低了

缺点:没办法检测方法实例,你只知道它是否说自己实现了接口。

ar CompositeImpl = function() { // 函数自己量
                 // 1. 显示的再类的内部   接收所实现的接口
                 // 一般来说是一个规范  我们项目经理: 在类的内部定义一个数组(名字要固定)        
                 this.implementsInterfaces = ['Composite', 'FormItem'] // 接口
             }
             
                 CompositeImpl.prototype.add = function(obj){
                     // do something
                     alert('Composite...')
                 }
                 
                 CompositeImpl.prototype.remove = function(obj){
                     // do something
                 }
                 
                 CompositeImpl.prototype.update = function(obj){
                     // do something
                 }
                 
                 CompositeImpl.prototype.select = function(obj){
                     // do something
                 }
                 
                 // 2. 检测 CompositeImpl类的对象的
                 function CheckCompositeImpl(instance){
                     //判断当前对象是否实现了所有的接口
                     if(!IsImplements(instance,"Composite","FormItem")){
                         throw new Error('这个实例没有继承')
                     }
                 }
                 
                 // 3. 公用的具体的检测方法(核心方法) 返回值类型  boolean
                 // 这个方法的主要目的:就是    判断 实例对象 有没有去实现相关的接口
                 function IsImplements(object){
                     // arguments 对象 获得函数的
                     for(var i = 1; i< arguments.length; i++){
                         // 接收所实现的每一个接口的名字
                         var interfachName = arguments[i];
                         // 判断次方法到底成功  还是失败
                         var interfaceFound = false;
                         
                         for(var j = 0; j < object.implementsInterfaces.length; j++){
                             if(object.implementsInterfaces[j] == interfachName){
                                 interfaceFound = true;
                                 break;
                             }
                         }
                         if(!interfaceFound){
                             return false;
                         }
                     }
                     return true;
                 }
             
             var c1 = new CompositeImpl();
             CheckCompositeImpl(c1)
             c1.add()

3、鸭式辨型法:推荐

观点:一个类实现接口的主要目标: 把接口里的方法都实现(检测方法),完全面向对象 代码也实现统一   也解耦了

// 一、接口类  Class Interface ==> 实例化N个接口
             
             /**
              * 接口类需要 两个参数
              * 参数一: 接口的名字 (String)
              * 参数二: 接收方法名称的集合(数组)
              */
             
             var Interface = function(name,methods){
                 //1、判断接口的参数个数
                 if(arguments.length != 2){
                     throw new Error("error")
                 }
                 this.name = name;
                 this.methods = []; //定义一个内置的空数组对象   等待接收methods里的元素(方法名字)
                 for(var i = 0, len = methods.length; i < len; i++){
                     if(typeof methods[i] !== 'string'){
                         throw new Error("the Interface method name is error")
                     }
                     this.methods.push(methods[i])
                 }
             }
             
             //二、准备工作: 具体的实现类
             //1. 实例化接口对象
             var CompositeInterface = new Interface("CompositeInterface",['add','remove']);
             var FormItemInterface = new Interface("FormItemInterface",['update','select']);
             
             //2. 具体实现的类
             var CompositeImpl = function(){
                 
             }
             
             //3. 实现接口的方法 implements methods
             CompositeImpl.prototype.add = function(obj){
                 alert('add')
                 // do something
             }
             
             CompositeImpl.prototype.remove = function(obj){
                 // do something
             }
             
             CompositeImpl.prototype.update = function(obj){
                 // do something
             }
 //            
 //            CompositeImpl.prototype.select = function(obj){
 //                // do something
 //            }
             
             //三、检验接口里的方法
             //如果检验通过  不做任何事情 往下执行; 不通过:浏览器抛出异常
             Interface.ensureImplements = function(object){
                 // 如果检测方法接受方法小于二      参数传递失败;
                 if(arguments.length < 2){
                     throw new Error("Interface ensureImplements method constructor arguments must be >= 2")
                 }
                 
                 //获的接口实例对象
                 for(var i = 1, len = arguments.length; i<len; i++){
                     var instanceInterface = arguments[i];
                     //判断参数是否是接口类的类型
                     if(instanceInterface.constructor !== Interface){
                         throw new Error("the arguments constructor not be Interface Class")
                     }
                     // 循环接口实例对象里面的每一个方法
                     for(var j = 0; j< instanceInterface.methods.length; j++){
                         //用一个临时变量 接收每一个方法的名字(注意是字符串)
                         var methodName = instanceInterface.methods[j];
                         if( !object[methodName] || typeof object[methodName] !== 'function'){
                             throw new Error("the method name '"+ methodName +"' is not found")
                         }
                     }
                 }
             }
             
             var c1 = new CompositeImpl();        
             Interface.ensureImplements(c1,CompositeInterface,FormItemInterface);
             c1.add()