摘要

js 语言并没有interface implement 关键字,如果要做到和后端语言类似的接口,一般会需要模拟实现。

在oo 编程中, 接口可以让架构师规定好模块必须要实现的方法, 尽量解耦模块。

实现接口的方法

第一种 注释法 , 只是一种约定,约束太小,而且不能保证接口是否完全实现

/*
interface Composite{
    function add(child);
}
interface fromItem{
    function save();
}
*/
var CompositeForm = function(id, method, action){

};
CompositeForm.prototype.add = function(child){

};
CompositeForm.prototype.save = function(){

};

第二种方法 属性判断, 虽然可以保证每个接口都实现,但是接口的方法是否实现也没法保证。

/*
interface Composite{
    function add(child);
}
interface fromItem{
    function save();
}
*/
var CompositeForm = function(){
    this.implementsInterfaces = ['Composite', 'FormItem']; //声明自己继承的接口
};

function addForm(formInstance){
    if(!implements(formInstance, 'Composite', 'FormItem')){ //检查实例formInstance是否实现了接口
        throw new Error('Object does not implement a required interface');
    }
}
function implements(object){ //检查算法,双重循环
    for(var i=1; 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;
        }
    }
    return true;
}

addForm(new CompositeForm());

第三种 鸭式辨型模仿接口 , 可以保证 实现每个 接口的方法, 但是引入了 Interface 这些类。

//Constructor
var Interface = function(name, methods){ //将接口的方法保存在this.methods中用以将来的检测
    if(arguments.length != 2){
        throw new Error('Interface constructor called with '+arguments.legth+
            " arguments, but exected exactly 2.");
    }

    this.name = name;
    this.methods = [];
    for(var i=0, len = methods.length; i<len; i++){
        if(typeof methods[i] !== 'string'){
            throw new Error('Interface constructor expects method names to be passed in as a string.');
        }
        this.methods.push(methods[i]);
    }
};

Interface.ensureImplements = function(object, arguments){
    if(arguments.length < 2){
        throw new Error('Function Interface.ensureImplements called with'+arguments.length+
            "arugments, but expected at least 2.");
    }
    for (var i=0, len = arguments.length; i<len; i++){
        var intf = arguments[i];
        if(intf.constructor !== Interface){
            throw new Error('Function Interface.ensureImplements expects arguments'+
                "two and above to be instances of Interface.");
        }
        for(var j=0, methodsLen = intf.methods.length; j < methodsLen; j++){
            var method = intf.methods[j];
            //通过methods检查实例是否实现了接口
            if(!object[method] || typeof object[method]!=='function'){
                throw new Error('Function Interface.ensureImplements:object'+
                    " doesnot implement the"+intf.name+
                    " interface. Method "+method+" was not found!");
            }
        }
    }
};

var Composite = new Interface('Composite', ['add']); //声明接口拥有的方法
var FormItem = new Interface('FormItem', ['save']); //声明接口拥有的方法

var compositeForm = function(id, method, action){//implements Composite, FormItem
};
compositeForm.prototype.add = function () {};
compositeForm.prototype.save = function () {};

function addForm(formInstance){
    Interface.ensureImplements.call(this, formInstance, [Composite, FormItem]);
}

addForm(new compositeForm());