Padrão - Singleton
Tags: webdev, javascript, cleancode, programming
Published: 2023-01-14 19:49:33


![Singleton Pattern](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uectxm6ncfnnawezx5o1.png)

O padrão Singleton é um dos padrões de projeto de software mais antigos e é amplamente utilizado em várias linguagens de programação. Ele foi originalmente descrito pelo engenheiro de software americano GoF (Gang of Four) no livro "Design Patterns: Elements of Reusable Object-Oriented Software" publicado em 1994.

O Singleton é um dos padrões creacionais que se concentra em garantir que uma classe tenha somente uma instância única em todo o ciclo de vida da aplicação e forneça um ponto global de acesso a essa instância. Esse padrão é muitas vezes usado em casos em que é necessário garantir que haja apenas uma única instância de uma classe, como gerenciadores de configurações, gerenciadores de conexões de banco de dados, gerenciadores de log, entre outros.

Existem algumas maneiras de implementar o padrão Singleton, mas a mais comum é criar uma variável de instância privada e estática para armazenar a instância única, e fornecer um método público estático ou de instância para obtê-la. Esse método verifica se a instância já foi criada e, se não foi, cria uma nova instância antes de retorná-la. Isso garante que haja apenas uma única instância da classe durante todo o ciclo de vida da aplicação e que essa instância possa ser acessada facilmente em todo o código.

O padrão Singleton tem algumas vantagens, que são:

- Garantia de uma única instância: O padrão Singleton garante que haja apenas uma única instância da classe em todo o ciclo de vida da aplicação, o que pode ser útil em casos em que é necessário garantir que haja apenas uma única fonte de verdade para um dado.
- Acesso fácil à instância única: O padrão Singleton fornece um ponto de acesso fácil à instância única, geralmente através de um método estático ou de instância específico, o que permite acessar a instância a partir de qualquer lugar do código.
- Controle de instanciação: O padrão Singleton permite controlar a instanciação da classe, o que é útil em casos em que é necessário garantir que a classe seja instanciada somente quando realmente necessário ou em casos em que é necessário restringir o número de instâncias da classe.
- Facilidade de implementação: O padrão Singleton é fácil de implementar e pode ser adicionado a uma classe existente sem muitas modificações.
- Performance: Criando uma única instância de um objeto pode melhorar o desempenho ao evitar a criação de múltiplas instâncias do mesmo objeto que pode consumir mais recursos do sistema.

Segue um exemplo da aplicabilidade do singleton em nodejs abaixo:

```js
class Logger {
  constructor() {
    if (Logger.instance) {
      return Logger.instance;
    }
    this.logs = [];
    Logger.instance = this;
  }

  log(message) {
    this.logs.push(message);
    console.log(`[${new Date().toISOString()}] ${message}`);
  }
}

const logger1 = new Logger();
logger1.log("Mensagem 1");

const logger2 = new Logger();
logger2.log("Mensagem 2");

console.log(logger1 === logger2); // true, é a mesma instancia

```

No exemplo acima, a classe _Logger_ tem uma propriedade estática chamada instance, que é usada para armazenar a única instância da classe. No construtor, verificamos se uma instância já foi criada e, se sim, retornamos essa instância ao invés de criar uma nova. Se não houver uma instância, criamos uma nova e armazenamos nela instance e adicionamos um array logs onde será armazenado as mensagem de log.

Ao criar novas instâncias de Logger usando o operador new, o construtor verifica se já existe uma instância e, se existir, retorna essa instância ao invés de criar uma nova. Desta forma, todas as instâncias dessa classe são a mesma instância, garantindo que haja apenas uma única fonte de verdade para o registro de log.

_Simples né?_

Imagine outro cenário onde cada iteração feita ao banco de dados é criado uma nova instancias de conexões, e com isso algumas inserções e alterações feitas o banco de dados no retorna o seguinte erro **_Too many connections_**. 

Para a diminuição do erro o nosso lider técnico informa que é necessário criar uma única conexão para o banco de dados com intuito de diminuir a quantidade de conexão.

Podemos solucionar com padrão _Singleton_, segue a resolução abaixo:

```js
const mysql = require('mysql2');

class Database {
  constructor() {
    if (Database.instance) {
      return Database.instance;
    }

    this.connection = mysql.createConnection({
        host: 'localhost',
        user: 'username',
        password: 'password',
        database: 'mydb'
    });
    this.connection.connect();

    Database.instance = this;
  }

  query(sql, args) {
    return new Promise((resolve, reject) => {
        this.connection.query(sql, args, (err, results) => {
            if (err) {
                return reject(err);
            }
            resolve(results);
        });
    });
  }
  
  close() {
    this.connection.end();
    Database.instance = null;
  }
}
```

Aqui, a classe _Database_ tem uma propriedade estática chamada instance, que é usada para armazenar a única instância da classe. No construtor, verificamos se uma instância já foi criada e, se sim, retornamos essa instância ao invés de criar uma nova. Se não houver uma instância, criamos uma nova e armazenamos nela instance com as configurações de conexão do banco de dados, e os métodos _query_ e _close_.

O query é usado para fazer consultas e o close para encerrar a conexão. Desta forma, todas as instâncias dessa classe são a mesma instância, garantindo que haja apenas uma única conexão com o banco de dados.


O padrão Singleton é útil quando precisamos garantir que haja apenas uma única instância de uma determinada classe em todo o sistema, e fornecer um ponto de acesso global para essa instância. Isso é útil em casos em que precisamos controlar o acesso a recursos compartilhados, como conexões de banco de dados, configurações de sistema, arquivos de log e muito mais.

Algumas outras situações em que o uso de Singleton é recomendado incluem:

- Quando precisamos garantir que um objeto só tenha uma instância em todo o sistema e fornecer um ponto de acesso global para ele.
- Quando precisamos controlar o acesso a recursos compartilhados, como arquivos de log, conexões de banco de dados ou configurações de sistema.
- Quando precisamos garantir que um objeto seja inicializado apenas uma vez e, em seguida, reutilizado várias vezes ao longo da vida útil do aplicativo.


**Conclusão**

O padrão Singleton é um padrão de projeto muito útil para garantir que haja apenas uma única instância de uma determinada classe em todo o sistema, e fornecer um ponto de acesso global para essa instância. 

**Observação**: _É importante ter cuidado para não exagerar no uso do Singleton. Ele pode causar problemas de desacoplamento e dificultar a testabilidade e manutenção do código._


Espero ter ajudado, até a próxima.