Factory constructor pattern

  1. Declaration
  2. Inheritance
  3. Private/protected methods (encapsulation)
  4. Summary
    1. Comparison with All-in-one constructor

This pattern is special, because it doesn’t use "new".
The object is created by a simple function call, similar to Python-style:

var animal = Animal("fox")
var rabbit = Rabbit("rab")

Declaration

The constructor is defined as a function which returns a new object:

function Animal(name) {
    
*!*
  return {
    run: function() {
      alert(name + " is running!")
    }
  }
*/!*

}

Usage:

var animal = Animal("fox")
animal.run()

Inheritance

Rabbit is made by creating an Animal, and then mutating it:

function Rabbit(name) {
    
  var rabbit = Animal(name) // make animal

  rabbit.bounce = function() { // mutate
    this.run()
    alert(name + " bounces to the skies! :)")
  }

  return rabbit // return the result
}

var rabbit = Rabbit("rab")
rabbit.bounce()

Private/protected methods (encapsulation)

Local variables and functions become private:

function Bird(name) {
    
*!*
  var speed = 100                    // private prop
  function openWings() { /* ... */ } // private method
*/!*

  return {
    fly: function() {
      openWings()
      this.move()
    },
    move: function() { /*...*/ }    
  }
}

The code above looks simple, but still there is a gotcha.

A public method can be called as this.move() from another public method, but not from a private method.

A private method like openWings can’t reference this. There’s no reference to the new object in a local function.

One way to solve that is to bind the new object to a local variable prior to returning:

function Bird(name) {
    
  function doFly() { 
    openWings()
*!*
    self.move()
*/!*
  } // private method


  *!*var self = */!*{
    fly: function() { doFly() },
    move: function() { /*...*/ }    
  }
  *!*return self*/!*
}

Summary

  • The factory constructor uses a function which creates an object on it’s own without new.
  • Inheritance is done by creating a parent object first, and then modifying it.
  • Local methods and functions are private. The object must be stored in closure prior to returning if we want to access it’s public methods from local ones.

Comparison with All-in-one constructor

The two methods: “All-in-one constructor” and the “Factory constructor”, described here, are actually the same.

Compare the two code pieces below. How similar they are.

function Animal(name) {
    //… 
}

function Rabbit(name) {
    var rabbit = Animal(name)
    
    var parentRun = rabbit.run
    
    rabbit.jump = function() {
      alert(name + " jumped!")
    }
    
    rabbit.run = function() {
      parentRun.call(this)
      alert("fast")
    }
    
    return rabbit
}

rabbit = Rabbit("rab")
function Animal(name) {
    // …
}

function Rabbit(name) {
  Animal.apply(this, arguments)

  var parentRun = this.run
    
  this.jump = function() {
    alert(name + " jumped!")
  }
  
  this.run = function() {
    parentRun.call(this)
    alert("fast")
  }
}

rabbit = new Rabbit("rab")

The result of both codes is same: they create a rabbit object with all methods assigned to it.

Initially, the object is created by literal on the left, and by new (as this) on the right.

Inheritance is performed similarly. The factory method uses rabbit = Animal() to get the parent object as rabbit. The all-in-one constructor uses Animal.apply(this, arguments) to get parent as this.

The only minor difference is syntax. Choose the one you’d prefer.

See also:

Tutorial

Donate

Donate to this project