JavaScript is a multi-paradigm programming language, so it provides us with a lot of different ways to deal with the same problem.
👉 What problem does factory pattern solve?
Factory pattern is used as a substitute for using classes.
For example, we want to create a couple of software developers who prefer different programming languages.
We can implement this behavior using class.
class SoftwareDeveloper {
constructor(language) {
this.language = language || 'C';
}
writeMessageInChat() {
console.log(`My favorite programming language is ${this.language}!`);
}
}
const Brendan = new SoftwareDeveloper('JavaScript');
const Guido = new SoftwareDeveloper('Python');
const Dennis = new SoftwareDeveloper();
Brendan.writeMessageInChat(); // My favorite programming language is JavaScript!
Guido.writeMessageInChat(); // My favorite programming language is Python!
Dennis.writeMessageInChat(); // My favorite programming language is C!
👉 What is a factory pattern?
Factory pattern uses factory functions to create objects instead of a class.
Simply put, a factory is just a function, that returns an object.
So, let's re-implement the exact same behavior using a factory function.
const SoftwareDeveloper = (language) => {
const lang = language || 'C';
return ({
writeMessageInChat: () => {
console.log(`My favorite programming language is ${lang}!`);
}
})
}
const Brendan = SoftwareDeveloper('JavaScript');
const Guido = SoftwareDeveloper('Python');
const Dennis = SoftwareDeveloper();
Brendan.writeMessageInChat(); // My favorite programming language is JavaScript!
Guido.writeMessageInChat(); // My favorite programming language is Python!
Dennis.writeMessageInChat(); // My favorite programming language is C!
👉 How to use it like a top-performer?
The factory pattern is very useful when you need to create a lot of objects, where some of the properties are the same.
That's exactly what React developers do in the createFactory
function.
/**
* Return a function that produces ReactElements of a given type.
* See https://reactjs.org/docs/react-api.html#createfactory
*/
export function createFactory(type) {
const factory = createElement.bind(null, type);
factory.type = type;
return factory;
}
// Example
import React from 'react';
const div = React.createFactory('div');
div(null, 'First div');
div(null, 'Second div');
div(null, 'Third div');
👉 Why is it legacy?
React v0.11 created a factory internally to deal with encapsulated components.
But this model was eventually considered conceptually wrong.
So the createFactory
function was introduced in React v0.12 to fix this issue.
// You write this
var Item = React.createClass(...)
// React v0.11 does this internally
class ItemClass {
}
function ItemFactory(...args) {
return React.createElement(ItemClass, ...args);
}
module.exports = ItemFactory;
// And you use it straight away
var Item = require('Item');
class App {
render() {
return Item({ text: 'Hello world!'});
}
}
// Or with JSX
var Item = require('Item');
class App {
render() {
return <Item text="Hello world!" />;
}
}
👉 React v0.12
The createFactory
function was a way to create components without creating an extra factory internally.
Simply put, React devs move the createFactory
from inside React.createClass
to the consuming module.
// You write this
var Item = React.createClass(...)
// React v0.12 do this internally
class Item {
}
module.exports = Item;
// But you need to call createFactory yourself
var Button = React.createFactory(require('Item'));
class App {
render() {
return Item({ text: 'Hello world!'});
}
}
// Or just let JSX do its job
var Item = require('Item');
class App {
render() {
return <Item text="Hello world!" />;
}
}
In the current state, React doesn't need the createFactory
function, because it deals with components without an extra factory.
P.S. Follow me on Twitter for more content like this!