A design pattern is a general, reusable solution to a commonly occurring problem. In this article we are going to look at some common design patterns we can use for Node.js.
Design patterns we are going to investigate are:
- Dependency Injection
- Factories
- Middlewares
- Observers
- Singlestons
- Streams
Dependency Injection
Dependency injection is a software design pattern in which one or more dependencies (or services) are injected, or passed by reference, into a dependent object.
Let’s look at an example where we pass a database as a dependancy.
function employeeModel (opt) {
var db;
if (!opt.db) {
throw new Error('opt.db is not defined');
}
db = opt.db;
return {
create: function (done) {
db.query('SELECT ...', done);
}
}
}
module.exports = employeeModel;
Factories
This pattern provides us with a generic interface for creating object, so we don’t have to worry about the nitty-gritty of the complex constructors.
function Employee(opt) {
this.opt = opt;
}
function create(opt) {
// modify the options here
return new Employee(opt);
}
module.exports.create = create;
Factories
Factories make testing much easier as you can inject module dependencies using this pattern.
Middlewares
Middlewares (or pipelines) are an essential part of Express, where the output of one unit is the input of the next.
Let’s look at an example
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.listen(3000);
Observers
The observers notify the owner object on state changes automatically. In Node.js we can use EventEmitter
to implement this pattern.
var util = require('util');
var EventEmitter = require('events').EventEmitter;
function EmployeeObservable() {
EventEmitter.call(this);
}
util.inherits(EmployeeObservable, EventEmitter);
Now we can use this observable by adding some functionality to it.
EmployeeObservable.prototype.login = function (name) {
this.emit('Logged in as ', name);
};
Now our observable can emit event.
var EmployeeObservable = require('EmployeeObservable');
var observable = new EmployeeObservable();
observable.on('Logged in as ', function (name) {
console.log(name);
});
observable.login('Sam');
Singlestons
By using singleton pattern we are making sure that the number of instances of a class is restricted to one.
var PI = Math.PI;
function circle (radius) {
return radius * radius * PI;
}
module.exports.circle = circle;
Now let’s use this module to instantiate an object.
var area = require('./area');
console.log(area.circle(5));
Most Common Node.js Pattern
Because require is common in Node.js, that makes the most common pattern.
Streams
Stream are like special pipelines, designed for complex operations like processing large amounts of flowing data.
process.stdin.on('readable', function() {
var buffer = process.stdin.read(5);
console.dir(buffer);
process.stdin.read(0);
});
The console output will be like:
(echo abc; sleep 1; echo def; sleep 1; echo ghi) | node consume2.js
Output:
<Buffer 61 62 63>
<Buffer 0a 64 65>
<Buffer 66 0a 67>
<Buffer 68 69 0a>
Conclusion
It is totally up to you when to use patterns in Node.js, but having this knowledge in your toolbox will come handy.