Design patterns are typical solutions to common problems in software design. Each pattern is like a blueprint that you can customize to solve a particular design problem in your code.

If you are facing a problem designing software it is quite probable that somebody faced it before. Take a look at the most common patterns because you can be lucky and somebody created a pattern to solve that problem.

They are a toolkit of tried, optimized and tested solutions to common problems in software design. Even if you never encounter these problems, knowing patterns is still useful because it teaches you how to solve all sorts of problems using principles of OO design.

Design patterns also improve communication in teams. If you say: “Hey, I’m creating a Factory to solve that”, everyone will understand the idea behind your suggestion. No need to explain what a Factory is if you know the pattern and its name.

Let’s start with some useful patterns in Node and what they help to solve.

Factory pattern

It’s a fact that in JS functional paradigm is often preferred to OO design. That’s specially true when creating new object instances. Creating a new object from a prototype using the new operator or Object.create() isn’t exactly flexible or convenient in several respects.

A factory allows us to separate the object creation from its implementation. It acts as a wrapper of the new instance. Inside the factory we can use what pointed in previous paragraph, closures, creating different instances a combining. Basically, everything what you need. The consumer will be agnostic about what is happening inside.

By other hand, JS doesn’t have a way to define public or private methods in a function, but, with factories we can enforce encapsulation.

Through this way we rely the engineer creation to the factory, so consumer can abstract from it. By other hand, privateSkills is not accessible from outside the function forcing the encapsulation.

Proxy pattern

A proxy is an object that controls access to another object, called subject. Both have identical interface and this allows us to transparently swap one for the other. A proxy intercepts all or some of the operations that are meant to be executed on the subject, modifying their behavior.

A proxy is useful to several circumstances like data validation, security, caching, lazy loading, logging or making remote object appear like local.

There are some techniques for implementing proxies like object augmentation, object composition or just use the Proxy object introduced in ES6. Composition can be considered the safest way of creating a proxy as it doesn’t modify the subject so we are going to use it in the code example.

Proxy pattern

It can be done with prototypes as well but I prefer to take advantage of all flexibility that JS offers.

In this case the proxy intercepts the hello method modifying the outcome and delegate the goodbye method. It’s possible you need to delegate most methods for a large function. In that case delegates NPM package should help.

Decorator pattern

It’s pretty similar to proxy, but instead of enhancing or modifying the behavior, it augments with new functionalities. The difference with inheritance is that decorator doesn’t add the behavior to all the objects of the same class, only to the instances that are decorated. Like in the proxy patterns, composition and object augmentation are the main techniques.

Decorator pattern

The DecoratedUser receives two arguments that help to modify the say function. The structure is pretty similar but the method behavior has changed.

Middleware pattern

It represents a processing pipeline similar to streams. In Node, this pattern is used well beyond the boundaries of the Express framework. It can be a set of processing units, handlers, filters, and any function to perform the preprocessing and post processing of any kind of data. It gives flexibility, in fact, allows us to obtain a plugin infrastructure with little effort, providing an unobtrusive way for extending a system with new filters and handlers.

Middleware pattern

In this representation, we have an incoming request, that, begore getting into the core of aour app, traverses a number of middlewares. This part of the flow is called inbound or downstream. After the flow reaches the core app, it traverses again all the middlewares in inverse order, so they can perform actions after app logic was executed. This part is known as outbound or upstream.

I created an example with ZeroMQ, to abstract the preprocessing and post processing of the data passing through a ZMQ socket, so that we can transparently work with JSON objects (serialize/deserialize), but also compress messages traveling over the wire.

You can find the code HERE. It consists in 4 files:

zmqMiddleware.js: The responsible for executing the middleware pipeline when a new message is received or sent.

jsonMiddleware.js: Middleware that serializes and deserializes JSON messages.

server.js: It binds a socket reply to local port 7000, creates an instance of the manager, added the JSON middleware and create an inbound function to handle requests coming from client

client.js: Connects through socket to local port 7000, creates an instance of the manager, added the JSON middleware, creates a function to handle responses coming from the server and finally sets up a timer that sends ping requests.

Command pattern

This is other pattern with huge importance in Node. A Command is any object that encapsulates all the information necessary to perform an action at a later time. So, instead of invoking a function directly, we create an object representing the intention to perform such an invocation. It’s built around four major components that can vary depending on the way we want to implement the pattern:

Command : The object encapsulating the information necessary to invoke a function.

: The object encapsulating the information necessary to invoke a function. Client: This creates the command and provides it to the invoker.

This creates the command and provides it to the invoker. Invoker: This is responsible for executing the command on the target.

This is responsible for executing the command on the target. Target: Subject of the invocation. It can be a lone function or the method of an object.

Using a command pattern has several advantages. Some of them are:

A command can be scheduled to be run at a later time

Keeps a history of operations executed in the system

Can be serialized and sent over the network so can be distributed.

A command scheduled can be cancelled if not executed yet

I created an example that allows undo and serialization. Code can be found HERE. It shows how wrapping an operation in a command can open a world of possibilities, and that’s just the tip of the iceberg