接口:提供一种说明一个对象应该有哪些方法的手段
JavaScript中有三种方式实现接口:
(1)注释描述接口
(2)属性检测接口
(3)鸭式辨型接口
1、注释描述接口:不推荐
优点:程序员有个参考,不需要额外的类或函数。
缺点:纯文档约束,程序不能检查实现接口的对象是否实现了所有接口方法
// CompositeImpl implements Composite
var CompositeImpl = function() { // 函数自己量
this.add = function(obj){
};
this.remove = function(obj){
}
}
CompositeImpl.prototype.add = function(obj){
// do something
}
CompositeImpl.prototype.remove = function(obj){
// do something
}
CompositeImpl.prototype.update = function(obj){
// do something
}
var c1 = new CompositeImpl();
var c2 = new CompositeImpl();
2、属性检测接口:不推荐
第二种方法要更严谨一点。所有类都明确地声明自己实现了哪些接口,那些想与这些类打交道的对象可以针对这些声明进行检查。那些接口自身仍然只是注释,但现在你可以通过检查一个属性得知某个类自称实现了什么接口。
优点:能够检查实现了哪些接口, 耦合性降低了
缺点:没办法检测方法实例,你只知道它是否说自己实现了接口。
ar CompositeImpl = function() { // 函数自己量
// 1. 显示的再类的内部 接收所实现的接口
// 一般来说是一个规范 我们项目经理: 在类的内部定义一个数组(名字要固定)
this.implementsInterfaces = ['Composite', 'FormItem'] // 接口
}
CompositeImpl.prototype.add = function(obj){
// do something
alert('Composite...')
}
CompositeImpl.prototype.remove = function(obj){
// do something
}
CompositeImpl.prototype.update = function(obj){
// do something
}
CompositeImpl.prototype.select = function(obj){
// do something
}
// 2. 检测 CompositeImpl类的对象的
function CheckCompositeImpl(instance){
//判断当前对象是否实现了所有的接口
if(!IsImplements(instance,"Composite","FormItem")){
throw new Error('这个实例没有继承')
}
}
// 3. 公用的具体的检测方法(核心方法) 返回值类型 boolean
// 这个方法的主要目的:就是 判断 实例对象 有没有去实现相关的接口
function IsImplements(object){
// arguments 对象 获得函数的
for(var i = 1; i< arguments.length; i++){
// 接收所实现的每一个接口的名字
var interfachName = arguments[i];
// 判断次方法到底成功 还是失败
var interfaceFound = false;
for(var j = 0; j < object.implementsInterfaces.length; j++){
if(object.implementsInterfaces[j] == interfachName){
interfaceFound = true;
break;
}
}
if(!interfaceFound){
return false;
}
}
return true;
}
var c1 = new CompositeImpl();
CheckCompositeImpl(c1)
c1.add()
3、鸭式辨型法:推荐
观点:一个类实现接口的主要目标: 把接口里的方法都实现(检测方法),完全面向对象 代码也实现统一 也解耦了
// 一、接口类 Class Interface ==> 实例化N个接口
/**
* 接口类需要 两个参数
* 参数一: 接口的名字 (String)
* 参数二: 接收方法名称的集合(数组)
*/
var Interface = function(name,methods){
//1、判断接口的参数个数
if(arguments.length != 2){
throw new Error("error")
}
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']);
//2. 具体实现的类
var CompositeImpl = function(){
}
//3. 实现接口的方法 implements methods
CompositeImpl.prototype.add = function(obj){
alert('add')
// do something
}
CompositeImpl.prototype.remove = function(obj){
// do something
}
CompositeImpl.prototype.update = function(obj){
// do something
}
//
// CompositeImpl.prototype.select = function(obj){
// // do something
// }
//三、检验接口里的方法
//如果检验通过 不做任何事情 往下执行; 不通过:浏览器抛出异常
Interface.ensureImplements = function(object){
// 如果检测方法接受方法小于二 参数传递失败;
if(arguments.length < 2){
throw new Error("Interface ensureImplements method constructor arguments 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];
if( !object[methodName] || typeof object[methodName] !== 'function'){
throw new Error("the method name '"+ methodName +"' is not found")
}
}
}
}
var c1 = new CompositeImpl();
Interface.ensureImplements(c1,CompositeInterface,FormItemInterface);
c1.add()