javascript设计模式开篇:Javascript 接口的实现

  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

  哈哈,有了接口的定义及实现后,你就可以在设计模式中充分发挥你的才能了,让设计模式为我们服务吧!

javascript设计模式开篇:Javascript 接口的实现,布布扣,bubuko.com

javascript设计模式开篇:Javascript 接口的实现

上一篇:SpringMVC+Apache Shiro+JPA(hibernate)案例教学(三)给Shiro登录验证加上验证码


下一篇:Java基础之静态变量