JavaScript中的接口模式的运行示例或工作演示

Anm*_*raf 9 javascript oop design-patterns interface

我正在阅读"专业javascript设计模式"一书,并且在理解第2章中给出的"界面"模式时遇到一点困难,因为没有完整的代码示例演示这种模式的使用.

我正在寻找一些帮助理解这个模式与一些运行代码示例可能在jsfiddle等.

这个模式在第14-22页的书中有解释,我不明白的主要观点是调用"addForm"方法的位置和方式.或者,如果有人可以使用一些测试数据和对象完成ResultFormatter示例,这对理解模式非常有帮助.

"Pro Javascript设计模式"一书的代码可以从http://jsdesignpatterns.com/下载,这是第2章.

谢谢您的帮助 !!

rod*_*ira 9

我已经看到了以不同方式实现的模式,但这个想法很简单:

  1. 你有一些类 - 你的接口 - 只是指定一些函数的名称.(您可能希望有一个名为Interface的类,您的实际接口实例化,因此您的接口类型为Interface)
  2. 然后你有一些其他类来实现这样的接口.这意味着第二个类必须至少具有接口指定的所有函数.
  3. 最后,你在其他地方有一些其他功能,它希望接收一个实现接口的对象.在您提到的示例代码中,此函数是addForm,它需要一个实现'Composite'和'FormItem'接口的对象.
  4. 然后,该函数遍历它所期望的接口的所有方法,并检查传递给它的对象是否也具有这些方法.如果在传递给函数的对象中找不到来自其中一个接口的方法,则它确定该对象未实现该接口,并抛出异常.

有些人可能会发现这种模式不实用,因为涉及到开销,但鉴于Javascript缺乏对接口的原生支持,这不是一个太糟糕的解决方案.有些人可能还会发现在Javascript中使用小型项目的接口是过度的.

var Interface = function(name, methods) {
    this.name = name;
    this.methods = [];

    if (methods.constructor == Array)
        this.methods = methods;
    else if (methods.constructor == String)
        this.methods[0] = methods;
    else
        throw new Error("Interface must define methods as a String or an Array of Strings");
};

var InterfaceHelper  = {
    ensureImplements : function(obj, interfaces) {
       // If interfaces is not an array, assume it's a function pointer
       var toImplement = interfaces.constructor == Array ? interfaces : [interfaces];
       var interface;

       // For every interface that obj must implement:
       for (var i = 0, len = toImplement.length; i < len; i++) {
          interface = toImplement[i];

          // Make sure it indeed is an interface
          if (interface.constructor != Interface)
             throw new Error("Object trying to implement a non-interface. "
             + interface.name + " is not an Interface.");

          // Make sure obj has all of the methods described in the interface
          for (var j = 0, interfaceLen = interface.methods.length; j < interfaceLen; j++)
             if (!obj[interface.methods[j]])
                throw new Error("Interface method not implemented. " 
                + interface.name + " defines method " + interface.methods[j]);
       }

       return true;
    }
};

var Drawable = new Interface("Drawable", ["onDraw"]);

var Surface = function() {
   this.implements = ["Drawable"];

   this.onDraw = function() {
      console.log("Surface Drawing");
   };
};
Run Code Online (Sandbox Code Playgroud)

用法

var myDrawableSurface = new Surface();

// Returns true
InterfaceHelper.ensureImplements(myDrawableSurface, Drawable);

// Returns false (Error thrown)
InterfaceHelper.ensureImplements(myDrawableSurface, Array);
Run Code Online (Sandbox Code Playgroud)


Anm*_*raf 5

完成了这本书的例子,这里是工作的jsfiddle, -

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.");
            }
        }
    }
};

function Map() {}

Map.prototype.centerOnPoint = function(x,y) {
    alert('center=> x: ' + x + ', y: ' + y);
};

Map.prototype.zoom = function(x){
    alert('zoom : ' + x);
}

Map.prototype.draw = function(){
    alert('draw');
};

var map = new Map();
var DynamicMap = new Interface('DynamicMap', ['centerOnPoint', 'zoom', 'draw']);

function displayRoute(mapInstance) {
    Interface.ensureImplements(mapInstance, DynamicMap);
    mapInstance.centerOnPoint(12, 34);
    mapInstance.zoom(5);
    mapInstance.draw();
}

displayRoute(map);?
Run Code Online (Sandbox Code Playgroud)