如何使用JavaScript创建此API并分析方法

时间:2012-10-22 07:22:52

标签: javascript design-patterns api-design

假设我想让这个API作为应用程序的示例:

var db = new Database('db-name'); // DB connection
var todo = new Todo(db); // New "Todo" and pass it the DB ref
// I want this API:
todo.model.create('do this', function (data) {
  console.log(data);
});

我现在设置如下:

function Todo (storage) {
  this.storage = storage;
};

Todo.prototype.model = {
  create: function (task, callback) {
    // The problem is "this" is Todo.model
    // I want the "super", or Todo so I can do:
    this.storage.save(task, callback);
  }
}

因此,如果您看到评论,问题是this内部的“model.create”显然引用了Todo.model,但我需要它来抓住“super }”。

我能想到的最好的是:

Todo.prototype.model = function () {
  var self = this;
  return {
    create: function (task, callback) {
      // The problem is "this" is Todo.model
      // I want the "super", or Todo so I can do:
      self.storage.save(task, callback);
    }
  }
}

但这两个都不是很好。最大的问题是我不希望在单个对象(第一个示例)或函数(第二个)中的model上拥有所有方法。我希望能够从模型def中取出它们。其次,我想要todo.model.create API。

是否有设计模式来实现这一目标?

3 个答案:

答案 0 :(得分:1)

由于todo.modelmodel属性,因此您无法使用todo原型模式。

我认为你需要:

  1. 一个新的Model对象,可以使用原型模型。

  2. Todo构造函数中,创建一个Model对象。理想情况下,使用只读“getter”函数来允许访问该模型对象,但不能覆盖该模型对象。

答案 1 :(得分:1)

使用bind,您可以执行以下操作:

function Todo (storage) {
  this.storage = storage;
  this.model = {};

  var methodNames = Object.keys(TodoModel);

  for(var i = 0; i < methodNames.length; ++i) {
    var methodName = methodNames[i];
    var method = TodoModel[methodNames];

    model[methodName] = method.bind(this);
  }
};

var TodoModel = {
  create: function(task, callback) {
    // Note that when this method is called using Todo.model.create,
    // 'this' will point to the Todo instance.
    this.storage.save(task, callback);
  }
};

function test(storage) {
  var todo = new Todo(storage);
  var task = {};

  todo.model.create(task, function(err, savedTask) {
    // ...
  });
}

TodoModel基本上是一张地图,因此您可以将其替换为地图集合,您将不再需要致电Object.keys

答案 2 :(得分:0)

您可以在构造函数中设置model,如下例所示:

function Todo (storage) {
  var self = this;

  this.storage = storage;

  this.model = {
    create: function(task, callback) {
      self.storage.save(task, callback);
    }
  };
};

或者,您可以使用bind,但我认为它会使事情变得更加复杂,因为您必须找到适用于旧浏览器的实现,并且它不会与支持EcmaScript的新浏览器中的本机实现冲突5。