JS设计模式——2.初识接口

什么是接口

接口提供了一种用以说明一个对象应该具有哪些方法的手段。

接口之利

1.接口具有自我描述性从而促进代码的重用

2.接口有助于稳定不同中的类之间的通信方式

3.测试和调试也变得更轻松

接口之弊

1.在一定程度上强化了类型的作用

2.js中没有内置的interface,实现它会增加复杂度

3.实现接口会对性能造成一定的影响

4.无法强迫其他程序员遵守你定义的接口

三种方法在JS中模仿接口

注释法(这只是一种文档规范)

/*

interface Composite{

    function add(child);

    function remove(child);

    function getChild(index);

}

interface fromItem{

    function save();

}

*/

var CompositeForm = function(id, method, action){

    ...

};

CompositeForm.prototype.add = function(){

    ...

};

CompositeForm.prototype.remove = function(){

    ...

};

CompositeForm.prototype.getChild = function(){

    ...

};

CompositeForm.prototype.save = function(){

    ...

};

这种方法没有确保对象真正实现了正确的方法集而进行检查,也不会抛出错误以告知程序中有问题。

用属性检查模仿接口

/*

interface Composite{

    function add(child);

    function remove(child);

    function getChild(index);

}

interface fromItem{

    function save();

}

*/

var CompositeForm = function(id, method, action){

    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;

}

这种做法是只知其表不知其里。

用鸭式辨型模仿接口

类是否声明自己支持哪些接口并不重要,只要它具有这些接口中的方法就行。

var Composite = new Interface('Composite', ['add', 'remove', 'getChild']); //声明接口拥有的方法 var FormItem = new Interface('FormItem', ['save']); //声明接口拥有的方法 var compositeForm = function(id, method, action){//implements Composite, FormItem

    ...

};

...

function addForm(formInstance){

    ensureImplements(formInstance, Composite, formItem);

    ...

}



//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){

    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=arugments.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++){ //通过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 DynamicMap = new Interface('DynamicMap', ['centerOnPoint', 'zoom', 'draw']);

function displayRoute(mapInstance){

    Interface.ensureImplements(mapInstance, DynamicMap);

    mapInstance.centerOnPoint(12,34);

    mapInstance.zoom(5);

    mapInstance.draw();

    ...

}

 

你可能感兴趣的:(设计模式)