javascript中模仿接口(interface)

  没想到javascript还可以模拟接口,顿时觉得js更加强大,所以把《javascript设计模式》的内容摘录出来,供大家学习,内容稍有改动.

1.在javascript中引入接口的好处:

   接口具有自我描述性,可以促进代码的重用;有利于不同的类之间进行通信,在大型项目中尤其有用;有利于代码的测试和调试。


 

2.引入接口的弊端

   接口的引入强化了类型的作用,降低了语言的灵活性;带来额外的开销;无法强迫其他程序员遵守你定义的接口。


 

3.模仿接口的方法

   方法1:用注释描述   

View Code
 1 /*
 2   interface  composite{
 3     function add(child);
 4     function remove(child);
 5     function getChild(index);
 6   }
 7   interface FormItem{
 8     function save();
 9   } 
10 */
11 var CompositeForm = function(){
12     ...
13 }
14 
15 CompositeForm.prototype = {
16     add: function(child){...},
17     remove: function(child){...},
18     getChild: function(index){...},
19     save: function(){...}
20 }

 

 该方法的不足:主要属于程序文档的范围,对接口的遵守完全依靠自觉。

方法2:用属性检查模拟接口

  

View Code
/*
  interface  composite{
    function add(child);
    function remove(child);
    function getChild(index);
  }
  interface FormItem{
    function save();
  } 
*/
  var CompositeForm = function(){
     this.implementsInterfaces = ['Composite','FormItem'];
     ...
  }
  function addForm(formInstance){
    if(! implements(formInstance,'Composite','FormItem')){
        throw new Error('object does not omplement a required interface');
    }
    ...
  }
  
  function implements(object){
    for(var i=1;i<arguments.length;i++){
        var interfaceName = arguments[i];
        var found = false;
        for(var j=0;j<object.implementsInterfaces.length;j++){
            if(object.implementsInterfaces[j] === interfaceName){
                found = true;
                break;
            }
        }
        if(! found){
            return false;   //an interface was not found
        }
    }
    return true;
}

  该方法的特点是显示地声明自己支持什么接口,但是并未确保类真正实现了自称的接口。

方法3.鸭式变型模拟接口

   首先是Interface类的定义

  

View Code
 1 var Interface = function(name,methods){
 2     if(arguments.length != 2){
 3         throw new Error('....');
 4     }
 5     this.name = name;
 6     this.methods = [];
 7     for(var i=1; i< methods.lenght;i++){
 8         if(typeof method[i] !== 'string'){
 9             throw new Error(...);
10         } 
11         this.methods.push(methods[i]);
12     }
13 }
14 Interface.ensureImplements = function(object){
15     if(arguments.length < 2){
16         throw new Error(...);
17     }
18     for(var i=1;i<arguments.lenght;i++){
19         var interfaceName = arguments[i];
20         if(interfaceName.constructor !==Interface){
21             throw new Error(...);
22         }
23         for(var j=0; j<interfaceName.methods.length;j++){
24             var method = interfaceName.methods[j];
25             if(!object[method] || typeof object[method] !== 'function'){
26                 throw new Error(...);
27             }
28         }
29     }
30 }

  接下来模拟接口:

   

View Code
 1 /*
 2   interface  composite{
 3     function add(child);
 4     function remove(child);
 5     function getChild(index);
 6   }
 7   interface FormItem{
 8     function save();
 9   } 
10 */
11 var Composite = new Interface('Composition',['add','remove','getChild']);
12 var FormItem = new Interface('FormItem',['save']);
13 
14 var CompositeForm = function(){
15     ...
16 }
17 
18 function addForm(formInstance){
19     Interface.ensureImplements(formInstance,Composite,FormItem);
20     ...
21 }

特点:可以保证强制实施类实现接口,但是缺少自我描述,同时还需要一个辅助类(Interface)和辅助函数(ensureImplements)。


 

4.结论:

  模拟接口最好的办法同时使用注释和鸭式变型方法。其实模拟接口不是最难的,难点在于何时使用接口。

posted @ 2013-04-18 15:10  沙漠孤鹰1140  阅读(1014)  评论(2编辑  收藏  举报