Factory Function Pattern In-Depth

The Basics

// greeter.js
export default () => {
return {
greet() {
console.log('Hello World!');
}
};
}
// main.js
import Greeter from './greeter';
const greeter = Greeter();greeter.greet(); // prints Hello World!

Dependency Injection

// greeter.js
export default (outputStream) => {
return {
greet() {
outputStream.send(‘Hello World!’);
}
};
}
// main.js
import Greeter from './greeter';
import ConsoleOutputStream from './console-output-stream';
const consoleOutputStream = ConsoleOutputStream();
const greeter = Greeter(consoleOutputStream);
greeter.greet(); // prints Hello World!
// console-output-stream.js
export default () => {
return {
send(line) {
console.log(line);
}
};
}

Unit Testing

// test/greeter.js
import { expect } from 'chai';
import Greeter from '../greeter';
describe('greeter', () => {
it('should send a greeting to output stream', () => {
const outputStream = {
send(line) {
expect(line).to.equal('Hello World!');
}
};
const greeter = Greeter(outputStream);
greeter.greet();
});
});

Encapsulation

// greeter.js
export default (outputStream) => {
let _message = 'Hello World!';
return {
greet() {
outputStream.send(_message);
},
set message(message) {
_message = message;
},
get message() {
return _message;
}
};
}
// main.js
import Greeter from './greeter';
import ConsoleOutputStream from './console-output-stream';
const consoleOutputStream = ConsoleOutputStream();
const greeter = Greeter(consoleOutputStream);
greeter.message = 'Salutations Earth.';
greeter.greet(); // prints Salutations Earth.

Composition

// gesturer.js
export default (outputStream) => {
return {
wave() {
outputStream.send('*Waves hand*');
}
};
}
// main.js
import Greeter from './greeter';
import Gesturer from './gesturer';
import ConsoleOutputStream from './console-output-stream';
const consoleOutputStream = ConsoleOutputStream();
const greeter = Greeter(consoleOutputStream);
const gesturer = Gesturer(consoleOutputStream);
const wavingGreeter = Object.assign({}, greeter, gesturer);wavingGreeter.message = 'Salutations Earth.';
wavingGreeter.greet(); // prints Salutations Earth.
wavingGreeter.wave(); // prints *Waves hand*

Calling Sibling Methods

// head-scratcher.js
export default () => {
const self = {
scratch(location) {
console.log(`scratching ${location}`);
},
confused() {
self.scratch('head');
}
};
return self;
}

Bounded Method References

// offset.js
export default class Offset {
constructor(delta) {
this.delta = delta;
}
add(value) {
return value + this.delta;
}
}
// main.js
import Offset from './offset';
const increment = new Offset(1);console.log([1, 2, 3]
.map(increment.add.bind(increment))); // prints [ 2, 3, 4 ]
// offset.js
export default (delta) => {
return {
add(value) {
return value + delta;
}
};
}
// main.js
import Offset from './offset';
const increment = Offset(1);console.log([1, 2, 3]
.map(increment.add)); // prints [ 2, 3, 4 ]

Types

// duck.js
export default () => {
return {
get type() {
return 'duck';
},
speak() {
return 'quack';
}
};
}
// main.js
import Duck from './duck';
import Dragon from './dragon';
const animals = [Duck(), Dragon()];animals.forEach((animal) => {
switch(animal.type) {
case 'duck':
console.log('safe to pet');
break;
case 'dragon':
console.log('run away');
break;
default:
console.log('be careful');
}
}); // prints safe to pet, then run away

Self-Instantiating Dependencies Anti-Pattern

// gesturer.js
import ConsoleOutputStream from './console-output-stream';
export default () => {
const outputStream = ConsoleOutputStream();
return {
wave() {
outputStream.send('*Waves hand*');
}
};
}

--

--

--

Eat Drink Live Software

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Ronald Chen

Ronald Chen

Eat Drink Live Software

More from Medium

Modern day JavaScript ORMs

Introduction to Mongoose — A JavaScript ORM

Joined select with ‘knex’

Higher Order Functions — JS