node.js 中的对象工厂模式

Object factory pattern in node.js

我在重构一段代码时遇到一个案例,要求我在nodejs中使用对象工厂模式。所以我在示例代码中尝试了这种模式,并提出了一些疑问。

factoryTest.js

var createFactory = require("./createFactory").createObjects();

var helloWorldObject = createFactory.helloWorld("userOne");
console.log("helloWorldObject: "+JSON.stringify(helloWorldObject));

var byeWorldObject = createFactory.byeWorld("userTwo", 22);
console.log("helloWorldObject: "+JSON.stringify(helloWorldObject));
console.log("byeWorldObject: "+JSON.stringify(byeWorldObject));

createFactory.js

var createObjects = function() {
    console.log("received a request to create new object.")
    this.localObject = {};
};

createObjects.prototype.helloWorld = function(name){
    this.localObject = {};      // CASE 1 <<<--- how can this be removed?
    this.localObject.name = name;
    this.localObject.greeting = "Hello " +name;
    return this.localObject;
};

createObjects.prototype.byeWorld = function(name, age){
    this.localObject = {};      // CASE 2 <<<--- how can this be removed?
    this.localObject.name = name;
    this.localObject.age= age;
    this.localObject.greeting = "Bye " +name;
    return this.localObject;
};

exports.createObjects = function(){
    return new createObjects();
}
  1. 调用和创建新对象的方式是否符合对象工厂设计模式?
  2. 能否将 CASE 1 和 CASE 2 创建为空对象从 helloWorld 和 byeWorld 中删除(在上面的代码中标记为注释)?
  3. 工厂模式是否创建一个对象用于每个请求,或者工厂模式是否为每个请求创建新对象 "new"?

CASE1和CASE2保持不变时的输出

received a request to create new object.
helloWorldObject: {"name":"userOne","greeting":"Hello userOne"}
helloWorldObject: {"name":"userOne","greeting":"Hello userOne"}
byeWorldObject: {"name":"userTwo","age":22,"greeting":"Bye userTwo"}

去掉CASE1和CASE2时的输出

received a request to create new object.
helloWorldObject: {"name":"userOne","greeting":"Hello userOne"}
helloWorldObject: {"name":"userTwo","greeting":"Bye userTwo","age":22}
byeWorldObject: {"name":"userTwo","greeting":"Bye userTwo","age":22}

新版本:

createFactory.js

var objectFactory = function(){
    console.log("received a new factory request.")
    return new createObjects();
}

var createObjects = function() {
    console.log("received a request to create new object.");
    this.localObject = {};
};

createObjects.prototype.helloWorld = function(name){
    this.localObject.name = name;
    this.localObject.greeting = "Hello " +name;
    return this.localObject;
};

createObjects.prototype.byeWorld = function(name, age){
    this.localObject.name = name;
    this.localObject.age = age;
    this.localObject.greeting = "Bye " +name;
    return this.localObject;
};

module.exports.objectFactory = objectFactory;

factoryTest.js

var createFactory = require("./createFactory").objectFactory;

var helloWorldObject = createFactory().helloWorld("userOne");
console.log("helloWorldObject: "+JSON.stringify(helloWorldObject));

var byeWorldObject = createFactory().byeWorld("userTwo", 22);
console.log("helloWorldObject: "+JSON.stringify(helloWorldObject));
console.log("byeWorldObject: "+JSON.stringify(byeWorldObject));

输出

received a new factory request.
received a request to create new object.
helloWorldObject: {"name":"userOne","greeting":"Hello userOne"}
received a new factory request.
received a request to create new object.
helloWorldObject: {"name":"userOne","greeting":"Hello userOne"}
byeWorldObject: {"name":"userTwo","age":22,"greeting":"Bye userTwo"}

这种方法能消除问题吗?

很高兴知道,Factory 模式实际上 创建 对象。它不用于以任何方式重用它们。

如果你想重用它们,你应该使用所谓的object pool

现在,您的代码中存在一些问题。一切从这里开始:

exports.createObjects = function(){
    return new createObjects();
}

所以第一次使用 require("./createFactory").createObjects() 时,函数会被执行并创建新的工厂。现在,每次您使用该工厂时,都会开始使用同一个对象 - this.localObject。这意味着您没有项目集合,而不是每次使用 helloWorldbyeWorld.

时更改的单个项目
this.localObject.name = name;

您实际上不是创建新对象,而是使用已经创建的对象并更改其属性。如果你真的需要创建新对象,像这样的东西可能会有帮助:

function createObjects() {
    this.objects = []; // store collection of objects
}

createObjects.prototype.helloWorld = function(name) {
    var obj = {
        name: name,
        greeting: "Hello " + name
    }
    this.objects.push(obj);
    return obj;
}

这将创建新对象并存储在集合中。如果你想删除它,你可以使用:

createObjects.prototype.removeObj = function(obj) {
    var index = this.objects.indexOf(obj);
    if (index != -1)
        this.objects.splice(index, 1);
}

现在您可以创建任何类型的函数来 create/delete 不同的对象,它们将是具有不同属性的独立对象。

p.s。 这种方法是拥有对象池的起点。但是你必须要么使用不同的列表,要么至少为那些对象设置属性,说明这个对象是否被使用。每次你想创建一个新的 - 检查是否有 "free" 对象,如果有 - return 它。如果没有 - 创建一个新的。


更新后,您实际上是在为每个 class 您想要的创建新工厂。每个工厂都包含 单个对象 ,您可以通过调用每个工厂的特定方法来修改这些对象。虽然这可能对您有用,但它不是真正的工厂模式。你为什么不在每次调用时创建新对象(你不需要它们被单独的函数使用,对吧)?类似于:

createObjects.prototype.helloWorld = function(name) {
    var result = {}; // CREATE brand new object
    result.name = name;
    result.greeting = "Hello " +name;

    return result;
};

这样你仍然可以使用一个工厂来处理不同的对象:

var createFactory = require("./createFactory").objectFactory(); // create only ONCE

var helloWorldObject = createFactory.helloWorld("userOne");
// -> userOne

var byeWorldObject = createFactory.byeWorld("userTwo", 22);
// -> userTwo

helloWorldObj == byeWorldObj // -> false, different objects