• 技术文章 >web前端 >js教程

    javascript设计模式 接口介绍_javascript技巧

    2016-05-16 17:51:48原创459
    这本书中第一个重要的内容就是接口。

    大家对接口应该都不陌生,简单的说接口就是一个契约或者规范。在强类型的面相对象语言中,接口可以很容易的实现。但是在javascript中并没有原生的创建或者实现接口的方式,或者判定一个类型是否实现了某个接口,我们只能利用js的灵活性的特点,模拟接口。
    在javascript中实现接口有三种方式:注释描述、属性验证、鸭子模型。
    note:因为我看的是英文书,翻译水平有限,不知道有些词汇如何翻译,大家只能领会精神了。
    1. 注释描述 (Describing Interfaces with Comments)
    例子:
    复制代码 代码如下:

    /*
    interface Composite {
      function add(child);
      function remove(child);
      function getChild(index);
    }
    interface FormItem {
      function save();
    }
    */
    var CompositeForm = function(id, method, action) { // implements Composite, FormItem
      ...
    };
    //Implement the Composite interface.
    CompositeForm.prototype.add = function(child) {
    ...
    };
    CompositeForm.prototype.remove = function(child) {
    ...
    };
    CompositeForm.prototype.getChild = function(index) {
    ...
    };
    // Implement the FormItem interface.
    CompositeForm.prototype.save = function() {
    ...
    };

    模拟其他面向对象语言,使用interface 和 implements关键字,但是需要将他们注释起来,这样就不会有语法错误。
    这样做的目的,只是为了告诉其他编程人员,这些类需要实现什么方法,需要在编程的时候加以注意。但是没有提供一种验证方式,这些类是否正确实现了这些接口中的方法,这种方式就是一种文档化的作法。
    2. 属性验证(Emulating Interfaces with Attribute Checking)
    例子:
    复制代码 代码如下:

    /* interface
    Composite {
    function add(child);
    function remove(child);
    function getChild(index);
    }
    interface FormItem {
    function save();
    }
    */
    var CompositeForm = function(id, method, action) {
    this.implementsInterfaces = ['Composite', 'FormItem'];
    ...
    };
    ...
    function addForm(formInstance) {
    if(!implements(formInstance, 'Composite', 'FormItem')) {
        throw new Error("Object does not implement a required interface.");
      }
      ...
    }
    // The implements function, which checks to see if an object declares that it
    // implements the required interfaces.
    function implements(object) {
      for(var i = 1; i < arguments.length; i++) {
        // Looping through all arguments
        // after the first one.
        var interfaceName = arguments[i];
        var interfaceFound = false;
        for(var j = 0; j < object.implementsInterfaces.length; j++) {
          if(object.implementsInterfaces[j] == interfaceName) {
            interfaceFound = true;
            break;
          }
        }
        if(!interfaceFound) {
          return false;
          // An interface was not found.
       }
      }
      return true;
    // All interfaces were found.
    }

    这种方式比第一种方式有所改进,接口的定义仍然以注释的方式实现,但是添加了验证方法,判断一个类型是否实现了某个接口。
    3.鸭子类型(Emulating Interfaces with Duck Typing)
    复制代码 代码如下:

    // Interfaces.
    var Composite = new Interface('Composite', ['add', 'remove', 'getChild']);
    var FormItem = new Interface('FormItem', ['save']);
    // CompositeForm class
    var CompositeForm = function(id, method, action) {
      ...
    };
    ...
    function addForm(formInstance) {
      ensureImplements(formInstance, Composite, FormItem);
      // This function will throw an error if a required method is not implemented.
      ...
    }
    // Constructor.
    var Interface = function(name, methods) {
      if(arguments.length != 2) {
        throw new Error("Interface constructor called with "
                 + arguments.length + "arguments, but expected exactly 2.");
      }
      this.name = name;
      this.methods = [];
      for(var i = 0, len = methods.length; i < len; i++) {
        if(typeof methods[i] !== 'string') {
          throw new Error("Interface constructor expects method names to be "
                  + "passed in as a string.");
        }
        this.methods.push(methods[i]);
      }
    };
    // Static class method.
    Interface.ensureImplements = function(object) {
      if(arguments.length < 2) {
        throw new Error("Function Interface.ensureImplements called with "
                  +arguments.length + "arguments, but expected at least 2.");
      }
    for(var i = 1, len = arguments.length; i < len; i++) {
        var interface = arguments[i];
        if(interface.constructor !== Interface) {
          throw new Error("Function Interface.ensureImplements expects arguments"
                  + "two and above to be instances of Interface.");
        }
        for(var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++) {
          var method = interface.methods[j];
          if(!object[method] || typeof object[method] !== 'function') {
            throw new Error("Function Interface.ensureImplements: object "
                    + "does not implement the " + interface.name + " interface. Method " + method + " was not found.");
          }
        }
      }
    };

    何时使用接口?
    一直使用严格的类型验证并不适合,因为大多数javascript程序员已经在没有接口和接口验证的情况下编程多年。当你用设计模式开始设计一个很复杂的系统的时候,使用接口更有益处。看起来使用接口好像限制了javascript的灵活性,但实际上他让你的代码变得更加的松耦合。他使你的代码变得更加灵活,你可以传送任何类型的变量,并且保证他有你想要的方法。有很多场景接口非常适合使用。
    在一个大型系统里,很多程序员一起参与开发项目,接口就变得非常必要了。程序员经常要访问一个还没有实现的api,或者为其他程序员提供别人依赖的一个方法存根,在这种情况下,接口变得相当的有价值。他们可以文档化api,并作为编程的契约。当存根被实现的api替换的时候你能立即知道,如果在开发过程中api有所变动,他能被另一个实现该接口的方法无缝替换。
    如何使用接口?
    首先要解决的问题是,在你的代码中是否适合使用接口。如果是小项目,使用接口会增加代码的复杂度。所以你要确定使用接口的情况下,是否是益处大于弊端。如果要使用接口,下面有几条建议:
    1.引用Interface 类到你的页面文件。interface的源文件你可以再如下站点找到: http://jsdesignpatterns.com/.
    2.检查你的代码,确定哪些方法需要抽象到接口里面。
    3.创建接口对象,没个接口对象里面包含一组相关的方法。
    4.移除所有构造器验证,我们将使用第三种接口实现方式,也就是鸭子类型。
    5.用Interface.ensureImplements替代构造器验证。
    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:设计模式 接口
    上一篇:javascript算法题 求任意一个1-9位不重复的N位数在该组合中的大小排列序号_javascript技巧 下一篇:Javascript中找到子元素在父元素内相对位置的代码_javascript技巧
    VIP课程(WEB全栈开发)

    相关文章推荐

    • 【腾讯云】年中优惠,「专享618元」优惠券!• 深入了解angular中的@Component装饰器• JavaScript面向对象详细解析之属性描述符• 详解node中如何安装多版本并进行切换• 什么是状态?深入学习angular中的动画• 浅析node中path路径模块的一些API
    1/1

    PHP中文网