javascript定义接口有3种方式
1注解描述的方式
2属性检测的方式
3鸭式辨型的方式
//1注解描述的方式
//优点:程序员有一个参考
//缺点:还是属于文档的范畴,这种方式太松散了,没有检查接口的方法是否完全被实现的
/*
* interface Composite{
* function add(obj);
* function remove(obj);
* function update(obj);
* }
*/
//CompositeImpl implements Composite
var CompositeImpl = function() {
};
CompositeImpl.prototype.add=function(obj){};
CompositeImpl.prototype.remove=function(obj){};
CompositeImpl.prototype.update=function(obj){};
var c1 = new CompositeImpl();
var c2 = new CompositeImpl();
alert(c1.add==c2.add);
//第二种实现接口的方式,属于属性检测的方式
/*
* interface Composite{
* function add(obj);
* function remove(obj);
* function update(obj);
* }
*
* interface FormItem{
* function select(obj);
* }
*/
//CompositeImpl implements Composite,FormItem
var CompositeImpl = function () {
//显示的在类的内部接受所实现的接口
//一般来说是一个规范,我们项目经理:在类的内部定义一个数组(名字要固定)
this.implememtsInterfaces=['Composite','FormItem'];
};
CompositeImpl.prototype.add=function(obj){
alert("add...")
};
CompositeImpl.prototype.remove=function(obj){};
CompositeImpl.prototype.update=function(obj){};
CompositeImpl.prototype.select=function(obj){};
function checkCompositeImpl(instance){
//判断当前对象是否实现了所有接口
if(!isImplements(instance,'Composite','FormItem')){
throw new Error("Object doesn't implement the required interface");
}
return true;
}
var comImpl = new CompositeImpl();
if(checkCompositeImpl(comImpl)){
comImpl.add();
}
//公用的具体的检测方法,返回值类型boolean
//这个方法的主要目的:就是判断实例对象有没有实现相关的接口
function isImplements(object,interfaces){
//arguments对象获得函数的实际参数
for(var i=1;i<arguments.length;i++){
//接受所实现的每一个接口的名字
var interfaceName = arguments[i];
//判断此方法到底成功还是失败呀
var interfaceFound=false;
for(var j=0;j<object.implememtsInterfaces.length;j++){
if(object.implememtsInterfaces[j]==interfaceName){
interfaceFound=true;
break;
}
}
if(!interfaceFound){
return false;
}
}
return true;
}
//实现接口的第三种方式:鸭式辨型法实现接口(最完美的javascript实现接口的方式)
//注解描述法,属性检测法
//鸭式辨型法实现的核心:一个类实现接口的主要目的:把接口里的方法都实现(检测方法)
//完全面向对象,代码也实现统一,也解耦了
//一: 接口类 Class Interface ===> 实例化N多个接口
/*
* 接口类需要2个参数吗?
* 参数1:接口的名字
* 参数2:接收方法名称的集合(数组)
*/
var Interface = function(name,methods){
//判断接口的参数个数
if(arguments.length != 2){
throw new Error("this instance interface constructor argument must be 2 length");
}
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']);
//CompositeImpl implements CompositeInterface,FormItemInterface
//2 具体的实现类
var CompositeImpl = function(){
}
//3 implements methods
CompositeImpl.prototype.add=function(obj){
alert("add...")
};
CompositeImpl.prototype.remove=function(obj){
alert("remove...")
};
CompositeImpl.prototype.update=function(obj){
alert("update...")
};
CompositeImpl.prototype.select=function(obj){
alert("select...")
};
//三: 检验接口里的方法
//如果检验通过,不做任何操作,如果不通过,浏览器抛出error
//这个方法的目的,就是检测方法的
Interface.ensureImplements=function (object) {
//如果检测的方法接受的参数个数小于2个,参数传递失败
if(arguments.length < 2){
throw new Error("Interface.ensureImplements method constructor arguments length 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];
//object[key]就是方法
if(!object[methodName] || typeof object[methodName] !== 'function'){
throw new Error("the method '" + methodName +"' is not found");
}
}
}
}
var c1 = new CompositeImpl();
Interface.ensureImplements(c1,CompositeInterface,FormItemInterface);
c1.add();