1

I came across a case while refactoring a piece of code that required me to use object factory pattern in nodejs. So I tried my hands with this pattern in sample code and came up with some doubts.

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. Is the way of calling and creating new objects as per object factory design pattern?
  2. Can CASE 1 and CASE 2 creation as empty object be removed from helloWorld and byeWorld(marked as a comment in code above)?
  3. Does factory pattern create a single object that gets used with each request OR Does factory pattern create new objects for each request as "new"?

Output when CASE1 and CASE2 are kept as is

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"}

Output when CASE1 and CASE2 are removed

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}

New version:

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));

Output

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"}

Does this approach eliminate issues?

1 Answer 1

2

It's good to know, that Factory pattern actually creates objects. It's not used to reuse them by any means.

If you want to reuse them, you should use the so called object pool.

Now, there are a few problems within your code. It all starts here:

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

So the first time you use require("./createFactory").createObjects(), the function gets executed and new factory is created. Now every time you use that factory, is starts to work with the very same object - this.localObject. Which means that you don't have collection of items, rather than a single one that you change every time you use helloWorld or byeWorld.

this.localObject.name = name;

You are actually not creating new object, but you use the one that is already created and change it's properties. If you need to really create new objects, something like this might be helpful:

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;
}

This creates new objects and stores is withing the collection. If you want to remove it, you could use:

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

Now you can make any kind of functions in order to create/delete different objects, and they will be separate ones with different properties.

p.s. This approach is the starting point of having an object pool. But then you must either use different lists or at least set properties to those object, stating if this object is used or not. And every time you want to create new one - check if there is "free" object and if so - return it. If not - create new one.


After your update, you are actually creating new factory for every class you want. And each factory contains single object that you modify by calling specific methods on each factory. While this might work for you, it's not an actual factory pattern. Why don't you create new object on each call (you won't need them used by separate functions, right)? Something like:

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

    return result;
};

This way you can still use one factory with different objects:

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
Sign up to request clarification or add additional context in comments.

5 Comments

I will come back to my 3rd question above. What should be the understanding behind a factory that creates object - create 1 object that is used by helloWorld & byeWorld. OR Create different objects each time helloWorld/byeWorld is called?
It's the latter. As stated in Lean JavaScript Patterns by Addy Osmani, Factory can provide a generic interface for creating objects, where we can specify the type of factory object we wish to be created.
Can you please have a look at new version and comment.
Thanks for the detailed answer. I have now made createObjects function as an empty function. Both helloWorld and byWorld have their own object declaration. Aside, in which case do we need multiple factories, as for my earlier update.
Usually, a factory creates specific type of objects. So multiple factories should create semantically different type of objects. For example gamesFactory can create few type of games. playersFactory creates different types of players, etc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.