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();
    ...
}

 


免責聲明!

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



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