Design Patterns em Node.js
Design patterns são soluções para problemas comuns no desenvolvimento de software. Eles permitem que desenvolvedores escrevam códigos mais legíveis, escaláveis e de fácil manutenção. Cada pattern funciona como um molde para solucionar problemas, trata-se de um conceito para uma solução, e não de uma solução pronta em código. A maioria dos patterns é bem descrita e documentada, o que os torna fáceis de serem reproduzidos.
Get Giulia Stefani’s stories in your inbox
Join Medium for free to get updates from this writer.
Aqui estão alguns dos patterns mais comuns e populares:
1. Module Pattern
Fundamental ao trabalhar com Node.js, esse pattern é usado para separar e encapsular código em diferentes módulos, “escondendo” os detalhes de implementação.
// logger.js
function log(message) {
console.log(`[LOG] ${message}`);
}
module.exports = { log };// app.js
const { log } = require('./logger');
log('Aplicação iniciada.');Usado para: Separar rotas, controllers, serviços.
2. Singleton Pattern
Um dos patterns mais populares, é utilizado quando é necessário garantir que exista apenas uma instância de uma determinada classe.
// database.js
class Database {
constructor() {
if (Database.instance) {
return Database.instance;
}
console.log('Conectando ao banco...');
this.connection = {}; // Simulação de conexão
Database.instance = this;
}
query(sql) {
console.log(`Executando query: ${sql}`);
}
}
module.exports = new Database();// app.js
const db1 = require('./database');
const db2 = require('./database');
db1.query('SELECT * FROM users');
console.log(db1 === db2); // trueUsado para: Conexão com banco de dados, configuração global.
3. Factory Pattern
Esse pattern utiliza um objeto como uma “fábrica” para criar novos objetos, aumentando a flexibilidade na criação de instâncias com diferentes configurações.
// userFactory.js
function createUser(type) {
if (type === 'admin') {
return { role: 'admin', permissions: ['read', 'write', 'delete'] };
}
return { role: 'user', permissions: ['read'] };
}
module.exports = { createUser };// app.js
const { createUser } = require('./userFactory');
const admin = createUser('admin');
const guest = createUser('guest');
console.log(admin);
console.log(guest);Usado para: Criação de serviços, usuários, objetos com configuração variada.
4. Dependency Injection Pattern
O Dependency Injection Pattern torna o código mais modular, testável e fracamente acoplado. Isso é feito injetando uma dependência em uma classe em vez de instanciá-la diretamente dentro dela.
// userService.js
function UserService(dbClient) {
return {
createUser: (data) => dbClient.insert('users', data)
};
}
module.exports = UserService;// fakeDb.js (mock para testes ou desenvolvimento)
const fakeDb = {
insert: (collection, data) => {
console.log(`Inserindo em ${collection}:`, data);
}
};
module.exports = fakeDb;// app.js
const fakeDb = require('./fakeDb');
const UserService = require('./userService');
const userService = UserService(fakeDb);
userService.createUser({ name: 'Maria', email: 'maria@example.com' });Usado para: Melhorar testabilidade e separação de responsabilidades.
5. Observer Pattern
Permite que um determinado objeto (observador) receba atualizações de outro objeto sempre que seu estado for alterado.
// notifier.js
const EventEmitter = require('events');
const notifier = new EventEmitter();
module.exports = notifier;// app.js
const notifier = require('./notifier');
// Registrar "observador"
notifier.on('userRegistered', (user) => {
console.log(`Novo usuário registrado: ${user.name}`);
});
// Em algum lugar do código:
notifier.emit('userRegistered', { name: 'João' });Usado para: Notificações, comunicação entre módulos.





