美文网首页
JS设计模式---2.接口

JS设计模式---2.接口

作者: 念丶凉 | 来源:发表于2018-12-08 22:29 被阅读10次

    什么是接口

    接口提供了一种用以说明一个对象应该具有哪些方法的手段。

    接口之利

    • 接口可以告诉一个程序员一个类实现了哪些方法,从而帮助其使用这个类。
    • 接口还有助于稳定不同类之间的通信方式。

    接口之弊

    • 接口的使用在一定程度上强化了类型的作用,这降低了语言的灵活性。
    • JS并没有提供对接口的内置支持,而试图模仿其他语言的内置功能总是会有一些风险
    • JS中任何实现接口的方法都会对性能造成一定影响,在某种程度上这得归咎于额外的方法调用的开销
    • 接口的使用最大的问题在于,无法强迫其他程序员遵守你定义的接口

    模仿接口实现

    • 用注释描述接口
    /*
      interface Composite {
         function add(child);
         function remove(child);
         function getChild(child);
      }
       interface FormItem {
         function save(child);
      }
    */
    var CompositeFrom = function(id,method,action){
       ...
    };
    CompositeFrom .prototype.add = function(child){
     ...
    };
    CompositeFrom .prototype.remove= function(child){
     ...
    };
    CompositeFrom .prototype.getChild= function(child){
     ...
    };
    CompositeFrom .prototype.save= function(child){
     ...
    };
    

    这种做法易于实现,不需要额外的类或函数。可以提高代码的可重用性。

    它的缺点在于没有为确保CompositeFrom真正实现了的正确方法而进行检查,也不会抛出错误告诉程序员程序中有问题,所以对于测试和调试也没有什么帮助。

    • 属性检查模仿接口
    /*
      interface Composite {
         function add(child);
         function remove(child);
         function getChild(child);
      }
       interface FormItem {
         function save(child);
      }
    */
    var CompositeFrom = function(id,method,action){
      //定义一个数组  存放将要实现的接口
      this.implementsInterface = ['Composite','FormItem'];
      ...
    };
    function addForm(formInstance){
      // 调用检查函数 如果存在未定义的接口 抛出错误
      if(!implements(formInstance,'Composite','FormItem')){
        throw new Error('Object does not implement a required interface')
      }
      ...
    }
    function implements(object){
      for (var i = 1;i<argumements.length;i++){
        // 遍历参数  跳过第一个 
        var interfaceName = argument[i]; //接口名称
        var interfaceFound = false ; //flag
        for (var j=0;j<object.implementsInterface.length;j++){
          // 遍历存放接口名称的数组
          if(implementsInterface[j] == interfaceName){
            interfaceFound = true;
            break;
          }
        }
        //  如果找到返回true  否则返回false
        return interfaceFound 
      }
    }
    

    这种方法不仅对所实现的接口进行了注释说明,如果需要的接口不在一个类所宣称支持接口之内,它还会抛出一个错误,这样就可以强迫其它程序员声明这些接口。

    它的缺点在于你不能保证所声明的接口是否真正实现。所以会存在检查通过,而方法不存在的问题。

    • 鸭式辨型模仿接口
    // Interface
    var Composite = new Interface('Composite',['add','remove','getChild']);
    var FormItem= new Interface('FormItem',['save']);
    //CompositeForm 类
    var CompositeForm= function(id,method,action){
     ...
    };
    functiom addForm(formIntance){
      // 辅助函数  如果引入未定义的接口会抛出错误
      ensureImplements(formIntance,Composite,FormItem);
      ...
    }
    

    这种方法不依赖于注释。其各个方面都是可以强制实施的。ensureImplements函数至少需要两个参数,第一个参数是想要检查的对象,其余参数是据以对那个对象进行检查的接口。

    它的缺点在于,类并不声明自己实现了哪些接口,降低了代码的可重用性,也缺乏上面两种方法的自我描述性。它依赖于辅助类Interface和辅助函数ensureImplements。

    Interface类的实现

    // 构造函数
    
     var Interface = function(name,methods){
        if(arguments.length != 2){  
          throw new Error(`Interface constructor called with ${arguments.length} arguments, but expcted 2.`);
        }
        this.name = name;
        this.methods = [];
        for(var i =0;i<methods.length;i++){
          if(typeof methodsp[i] !== 'string'){
            throw new Error("Interface  constructor expects method name to be passed in as a string");
          } 
          this.methods.push(methods[i]);
        }
    };
    // 辅助函数
    Interface.ensureImplements = function(object){
        //  如果参数小于2个抛出错误
        if(arguments.length<2){
          throw new Error(`Function Interface.ensureImplements called with ${arguments.length} arguments, but expected at least 2.`);
        }
        for(var i = 1; i<arguments.length; i++){
          var interface = arguments[i];
          // 如果类的构造函数不是Interface 抛出错误
          if(interface.constructor !== Interface){
            throw new Error("Function Interface.ensureImplements expects arguments two and above to be insterface of Interface")
          }
           // 遍历存放接口名称的数组
          for (var j=0;j<interface.methods.length;j++){
            var method = interface.methods[j]
            if(!object[method] || typeof method !== 'function'){
              throw new Error(`Function Interface.ensureImplements: object does not implement the ${interface.name} interface.Method ${method} was not found`)
            }
          }
        }
    }
    
    
    

    相关文章

      网友评论

          本文标题:JS设计模式---2.接口

          本文链接:https://www.haomeiwen.com/subject/smbxhqtx.html