重读《JavaScript设计模式》- 接口

接口

Class一样,JavaScript也没有对接口的原生支持.

下面是书中三种实现接口的方式:

  提示

实际环境中我们会对书中的方案进行取舍

  1. 注释

    注释法用文档来约束代码,不是强制约束,只能靠开发人员自觉维护.

    优点是不用额外代码支持,不会增大文件大小,不会影响执行速度.

    缺点是无法提供检查,错误信息.

     

    # interface Composite
    #   add(child)
    #   remove(child)
    #   getChild(index)
    #
    # interface FormItem
    #   save()
    
    CompositeForm = (id, method, action)->
        # implements Composit, FormItem
        <link xmlns="http://docbook.org/ns/docbook" xlink:href="%E5%AF%8C%E6%9C%89%E8%A1%A8%E7%8E%B0%E5%8A%9B%E7%9A%84JavaScript.xml" xmlns:xlink="http://www.w3.org/1999/xlink"/>...
    CompositeForm.portotype = 
        add: -> ...
        remove: -> ...
        getChild: -> ...
        save: -> ...
    

     

  2. 属性检查

    该方法可以检查某个对象是否标注实现了某些接口,但是不检查是不是实现了接口定义的方法.

     

    # interface Composite
    #   add(child)
    #   remove(child)
    #   getChild(index)
    #
    # interface FormItem
    #   save()
    
    CompositeForm = (id, method, action)->
        @implementsInterfaces = [‘Composite‘,‘FormItem‘]
        ...
    
    addForm = (formInstance)->
        if(!implements(formInstance, ‘Composite‘, ‘FormItem‘))
            throw new Error(‘Object does not implements a required interface.‘)
        ...
    
    # add to global / window
    glabol.implements = (object)->
        for i in [1...arguments.length] # interfaces
            if not arguments[i] in object.implementsInterfaces
                return false
        true
    

     

  3. 鸭式辨形

    这种方法在上一个基础上检查了实现接口的所有方法是否进行了实现.并新增一个Interface类来辅助接口设计.

     

    # interfaces
    Composite = new Interface ‘Composite‘, [‘add‘,‘remove‘,‘getChild‘]
    FormItem = new Interface ‘FormItem‘, [‘save‘]
    
    # class
    CompositeForm = (id,method,action)->
        ... # implements
    
    # business code
    addForm = (formInstance)->
        Interface.ensureImplements formInstance, Composite, FormItem
    
    # Interface class
    Interface = (name, method)->
        throw new Error("Interface constructor called with #{arguments.length} arguments, but expected exactly 2.") if arguments.length!=2
        
        @name = name
        @methods = []
        for method in methods
            throw new Error(‘Interface constructor expects method names to be passed in as a string.‘) if typeof method != ‘string‘
            @methods.push method
            
    # static class method
    Interface.ensureImplements = (object)->
        throw new Error("expected at least 2 arguments") if arguments.length<2
        
        for interface in arguments[1...arguments.length]
            throw new Error("Function Interface.ensureImplements expert argumnets two and above to be instances of Interface.") if interface.constructor != Interface
            for method in interface.methods
                if !object[method] || typeof object[method] != ‘function‘
                    throw new Error "object does not implemnet the #{interface.name} interface. Method #{method} was not found."
    

     

      提示

    如果使用了上面的接口实现,那么代码中的类型检查(instanceof)应该去掉,因为我们直接检查了方法的实现.

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。