Skip to main content
 首页 » 编程设计

javascript接口设计模式

2022年07月16日161pander-it
/** 
 * 接口是一种指定对象应该有哪些方法的技术,他不关心方法如何实现。 
 * 基于接口编程的好处是:实现相同接口的对象,可以互换,而不影响功能实现。 
 * 接口还有利于大项目中,多人合作的交流 
 */ 
/**************** 在js中模仿接口 ******************/ 
 
//用注释描述接口 
//效果最差,不会提供错误信息 
//易于实现 
/* 
 interface Composite { 
 function add(child); 
 function remove(child); 
 function getChild(index); 
 } 
 interface FormItem { 
 function save(); 
 */ 
 
var CompositeForm = function (id, method, action) { 
    //implements Composite, FormItem 
}; 
 
//implement the Composite interface 
CompositeForm.prototype.add = function (child) { 
 
}; 
CompositeForm.prototype.remove = function (child) { 
 
}; 
Composite.prototype.getChild = function (index) { 
 
}; 
 
//implement the formItem interface 
CompositeForm.prototype.save = function () { 
 
}; 
 
 
//用属性检查模仿接口 
/* 
 优点: 
 对类所实现的接口提供了文档说明 
 如果没有必须的接口会提示错误消息 
 缺点: 
 显示声明类所支持的接口,但没有真正检测接口是否存在 
 */ 
/* 
 interface COMposite { 
 function add(child); 
 function remove(child); 
 function getChild(index); 
 } 
 interface FormItem { 
 function save(); 
 } 
 */ 
var CompositeForm = function (id, method, action) { 
    //add interface into array 
    this.implementsInterfaces = ['Composite', 'FormItem']; 
    //... 
}; 
 
function addForm(formInstance) { 
    if (!implements(formInstance, 'Composite', 'formItem')) { 
        throw new Error('Object does not implement a required interface.'); 
    } 
    //... 
} 
 
//The implement function,which checks to see if an object declares that 
//it implements the required interface 
function implements(object) { 
    //looping through all arguments after the first one 
    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) { 
            //an interface was not found 
            return false; 
        } 
    } 
    //all interface were found 
    return true; 
} 
 
 
//用鸭式辩型模仿接口 
//如果对象具有与接口定义的方法同名的所有方法 
//那么就可以认为它实现了这个接口 
/** 
 * 三种方法中最有用的一种 
 * 缺点: 
 *     类并不声明自己实现了那些接口,降低了代码的可重用性 
 *     缺乏自我描述 
 *     不检查方法的参数 
 */ 
//Interface. 
var Composite = new Interface('Composite', ['add', 'remove', 'getChild']); 
var FormItem = new Interface('FormItem', ['save']); 
 
//CompositeForm class 
var CompositeForm = function (id, method, action) { 
    //... 
}; 
//... 
function addForm(formInstance) { 
    ensureImplements(formInstance, Composite, FormItem); 
    //this function will throw an error if a required method is not implemented 
    //... 
} 
 
 
//本书采用的接口实现方法 
//结合第一种和第三种方法 
//interfaces 
var Composite = new Interface('Composite', ['add', 'remove', 'getChild']); 
var formItem = new Interface('FormItem', ['save']); 
 
//CompositeForm class 
var CompositeForm = function (id, method, action) { 
    //... 
}; 
//... 
 
function addForm(formInstance) { 
    Interface.ensureImplements(formInstance, Composite, FormItem); 
    //this function will throw an error if a required method is not implemented 
    //halting execution of the function 
    //all code beneath this line will be executed only if the checks pass 
    //... 
} 
 
 
/************ Interface类 *************/ 
//Constructor 
var Interface = function (name, method) { 
    // 检测参数个数 
    if (arguments.length != 2) { 
        throw new Error('Interface constructor called with ' + arguments.length + 'arguments,ut expected exactly 2.'); 
    } 
    this.name = name; 
    this.methods = []; 
    //遍历方法 
    for (var i = 0, len = method.length; i < len; i++) { 
        //检查数组值是否字符串 
        //如果不是,抛出错误信息 
        if (typeof method[i] !== 'string') { 
            throw new Error('Interface constructor expects method names to be passed in as a string'); 
        } 
        //将方法名添加到属性数组中 
        this.methods.push(method[i]); 
    } 
 
}; 
 
//static class method 
Interface.ensureImplements = function (object) { 
    //参数个数必须大于等于2个 
    if (arguments.length < 2) { 
        throw new Error('Function Interface.ensureImplements called with ' + arguments.length + 'arguments,but expected at least 2.'); 
    } 
 
    //遍历除第一个参数的其他参数 
    for (var i = 1, len = arguments.length; i < len; i++) { 
        var interface = arguments[i]; 
        //如果不是Interface的实例,则抛出错误 
        if (interface.constructor !== Interface) { 
            throw new Error('Function interface.ensureImplements expectes arguments two and above to be instances of Interface.'); 
        } 
 
        //遍历实例中的方法 
        for (var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++) { 
            var method = interface.methods[j]; 
            //如果object没有实例中的方法,则抛出错误 
            if (!object[method] || typeof object[method] !== 'function') { 
                throw new Error('Function Interface.ensureImplements:object does not implement the ' + interface.name + 'interface. Method ' + method + ' was not found.'); 
            } 
        } 
    } 
}; 
 
 
//使用 
    var DynamicMap = new Interface('DybamicMap', ['centerOnPoint', 'zoom', 'draw']); 
 
    function displayRoute(mapInstance) { 
        Interface.ensureImplements(mapInstance, DynamicMap); 
        mapInstance.centerOnPoint(12, 34); 
        mapInstance.zoom(5); 
        mapInstance.draw(); 
        //... 
    } 
    var Test = function () { 
 
    }; 
    Test.prototype = { 
        centerOnPoint:function (a, b) { 
            console.log('centerOnPoint2'); 
        }, 
        zoom:function (num) { 
            console.log('zoom2'); 
        }, 
        draw:function(){ 
 
        } 
    }; 
    var a = new Test(); 
    displayRoute(a); 
 
 
//实例 
// ResultFormatter class,before we implement interface checking 
//未使用Interface类检测 
var TestResult = function () { 
 
}; 
TestResult.prototype = { 
    getDate:function () { 
 
    }, 
    getResults:function () { 
 
    } 
}; 
var ResultFormatter = function (resultsObject) { 
    // 是否为TestResult的实例 
    // 不是就抛出错误 
    if (!(resultsObject instanceof TestResult)) { 
        throw new Error('ResultsFormatter: constructor requires an instance of TestResult as an argument.'); 
    } 
    //将参数公有化 
    this.resultsObject = resultsObject; 
}; 
 
ResultFormatter.prototype.renderResults = function () { 
    var dateOfTest = this.resultsObject.getDate(); 
    var resultsArray = this.resultsObject.getResults(); 
 
    var resultsContainer = document.createElement('div'); 
    var resultsHeader = document.createElement('h3'); 
    resultsHeader.innerHTML = 'Test Results from ' + dateOfTest.toUTCString(); 
    resultsContainer.appendChild(resultsHeader); 
 
    var resultsList = document.createElement('ul'); 
    resultsContainer.appendChild(resultsList); 
    for (var i = 0, len = resultsArray.length; i < len; i++) { 
        var listItem = document.createElement('li'); 
        listItem.innerHTML = resultsArray[i]; 
        resultsList.appendChild(listItem); 
    } 
 
    //返回创建的DOM 
    return resultsContainer; 
}; 
/* 
 TestResult类可能被修改,致使其不再拥有getDate()方法 
 检查仍能通过,但renderResults方法却会失灵 
 不允许其他类的实例作为参数 
 */ 
 
//使用Interface类后 
//ResultSet interface 
var ResultSet = new Interface('ResultSet', ['getDate', 'getResults']); 
 
//ResultFormatter class, after adding Interface checking 
var ResultFormatter = function (resultsObject) { 
    Interface.ensureImplements(resultsObject, ResultSet); 
    this.resultsObject = resultsObject; 
}; 
 
ResultFormatter.prototype.renderResults=function(){ 
    //... 
}; 

  


本文参考链接:https://www.cnblogs.com/webFrontDev/archive/2012/12/16/2820374.html