javascript语言不像java、 c#、 c++等面向对象语言那样有完备的接口支持,在javascript中,接口的实现有三种方式,分别为注释描述、属性检查、鸭式变形。注释描述实现起来最为简单,但是,接口约定的遵守纯靠自觉,而且也没有很好的度量措施,说到底,它主要还是属于程序文档范畴。其实,类是否申明自己支持哪些接口并不重要,只要它具有这些接口中的方法就行了。鸭式变形(这个名称来自James Whitcomb Riley的名言:"像鸭子一样嘎嘎叫的就是鸭子")正式基于这种认识。
下面来谈谈javascript中接口的具体实现策略。(基于鸭式变形,用的也是最多的哦~~)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
<em id= "__mceDel" > * 接口类构造函数,接受2个以上的参数,其中第一个参数为接口名,后面的参数可以为字符串数组,也可以为字符串
* @param {Object} name
* 接口名
* @param {Object} methods
* 接口包含的方法集合,参数可以为数组,也可以传入任意多的字符串形式的方法名
*/
var
Interface = function (name, methods){
if (arguments.length < 2){ //若参数个数不为2,则抛出错误
throw
new Error( "Interface constructor called with"
+ arguments.length +
"arguments, but expected at least 2" );
}
this .name = name;
this .methods = [];
for ( var
i = 1, len = arguments.length; i < len; ++i){
if (arguments[i] instanceof
Array){ //若参数为数组,则遍历该参数
for ( var
j = arguments[i].length - 1; j > -1; --j){
if ( typeof
arguments[i][j] !== ‘string‘
){ //保证传入的方法名为字符串,否则抛出错误
throw
new Error( ‘Interface constructor expects method names to be passed in as a string‘ );
}
this .methods.push(arguments[i][j]); //保存方法名
}
} else
if ( typeof
arguments[i] === ‘string‘ ){ //参数为字符串,直接保存
this .methods.push(arguments[i]);
} else
{ //否则抛出错误
throw
new Error( ‘Interface constructor expects method names to be passed in as a string‘ );
}
}
}; /* * 接口实现检验函数,第一个参数为要检查的对象,后面的任意参数为实现的接口对象,也可以为接口对象数组
* @param {Object} object
*/
Interface.ensureImplents = function (object){
if (arguments.length < 2){
throw
new Error( "Interface constructor called with"
+ arguments.length +
"arguments, but expected at least 2" );
}
var
_checkMethods = function (inface){ //内部函数,用于检验对象是否实现了ifs对象中的方法
var
methods = inface.methods,
i = methods.length - 1;
for ( ; i > -1; --i){
var
method = methods[i];
//若对象不存在该属性,或者该属性不是方法,那么抛出错误
if ( typeof
object[method] === ‘undefined‘
|| typeof
object[method] !== ‘function‘ ){
throw
new Error( "Function Interface.ensureImplents: object does not implent the "
+
inface.name + "interface. Method "
+ method + " was not found."
);
}
}
};
for
( var
i = arguments.length - 1; i > 0; --i) {
if (arguments[i] instanceof
Array){
for ( var
j = arguments[i].length - 1; j > -1; --j){
if (!arguments[i][j] instanceof
Interface){
throw
new Error( ‘Function Interface.ensureImplents expects arguments two and above to be‘
+
‘instances of Interface‘ );
}
_checkMethods(arguments[i][j]); //检验接口实现
}
} else
if (arguments[i] instanceof
Interface){
_checkMethods(arguments[i]); //检验接口实现
} else
{
throw
new Error( ‘Function Interface.ensureImplents expects arguments two and above to be‘
+
‘instances of Interface‘ );
}
}
};</em> |
1
|
编写出上述代码挺简单,主要思路就是检测传入参数的类型和名称。看看某个具体实现类有没有实现所定义的接口中的那些 function 。。<br> 下面给出一个调用接口的例子吧~
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
//2个接口实例 var
ITest = new
Interface( ‘ITest‘ , ‘test0‘ , [ ‘test1‘ , ‘test2‘ ], ‘test3‘ );
var
ISay = new
Interface( ‘ISay‘ , ‘say0‘ , ‘say1‘ );
//未继承的任何对象,仅是实现了ITest接口 var
implentTest = {
test0: function (){
alert( ‘test0‘ );
},
test1: function (){
alert( ‘test1‘ );
},
test2: function (){
alert( ‘test2‘ );
},
test3: function (){
alert( ‘test3‘ );
}
} var
implentSay = {
say1: function (){
alert( ‘say1‘ );
},
say0: function (){
alert( ‘say0‘ );
}
}; function
TestAndSay (){
this .say0 = function (){
alert( ‘test0 and say0‘ );
};
this .say1 = function (){
alert( ‘tes1t and say1‘ );
};
} TestAndSay.prototype = implentTest; //一个简单的继承
var
implentTestAndSay = new
TestAndSay(); //实例化
function
test(ITestInstance){
Interface.ensureImplents(ITestInstance, ITest);
ITestInstance.test0();
ITestInstance.test1();
ITestInstance.test2();
} function
say(ISayInstance){
Interface.ensureImplents(ISayInstance, ISay);
ISayInstance.say0();
ISayInstance.say1();
} function
sayAndtest(inst){
Interface.ensureImplents(inst, ISay, ITest);
inst.test0();
inst.say0();
inst.say1();
} test(implentTest); //弹出3个对话框:test0 test1 test2
//test(implentSay);将会抛出错误 //say(implentTest); 将会抛出错误 say(implentSay); //弹出2个对话框 say0 say1
sayAndtest(implentTestAndSay); //弹出3个对话框: test0; test0 and say0; test1 and say1
|
哈哈,有了接口的定义及实现后,你就可以在设计模式中充分发挥你的才能了,让设计模式为我们服务吧!