Singleton
O que é?
- Um design pattern que possui essas principais características:
- Restrige a somente uma instância de uma classe
- A instância só é criada ao ser chamada explicitamente
- Não passa parâmetros na criação (método construtor)
- Objeto pode ser acessada globalmente para toda aplicação
- Normalmente o método construtor é privado
- Pode limitar o acesso simultâneo a um recurso compartilhado
- Possui um método chamado
getInstance
- Responsável na criação do objeto
- Retorna o novo objeto (caso for a primeira instância)
- Se a classe já tenha sido instanciada, é retornado o objeto existente
Casos de Uso
- Três casos mais comuns de uso desse design pattern:
- Sistema de logs
- Sempre jogando os logs no mesmo objeto
- Conexão única ao banco de dados
- Instância única que possui acesso ao banco de dados
- Garante que não haja novas instâncias
- Assim, impedindo que novas conexões sejam estabelecidas
- Acesso ao sistema de arquivos de um sistema
- Criando ponto único de acesso para modificação de arquivos
- Impedindo alteração simultânea de um arquivo
Exemplo de código
counter.jslet instance;
let counter = 0;
class Counter {
constructor() {
if (instance) {
throw new Error("You can only create one instance!");
}
instance = this;
}
getInstance() {
return this;
}
getCount() {
return counter;
}
increment() {
return ++counter;
}
decrement() {
return --counter;
}
}
const singletonCounter = Object.freeze(new Counter());
export default singletonCounter;
Por que anti-pattern?
- Listo abaixo os 5 motivos pelos quais não utilizar esse pattern
- Pelo menos em sua implementação mais simplória
- Não é Thread safe
- Não foi pensada em casos como Paralelismo, Concorrência, Sistemas Distribuídos
- Pois se dois contextos diferentes interagirem com o objeto, bugs poderam ocorrer
- Porque o objeto não é protegido (lock) quando modificado por um contexto (thread)
- Alto acoplamento
- Deve-se sempre chamar o método
getInstance para ter acesso ao meu objeto
- Criando alto acomplamento, algo que na POO não é visado!
- Acesso global de um objeto
- Tendo acesso em qualquer parte da minha aplicação
- Se eu modificar as propriedades do objeto em um canto da app
- Eu modifico ela globalmente, em minha app inteira
- Dificuldade ao trabalhar com testes
- De forma unitária, deveriámos criar novas instâncias, não reutilizar uma instância já existente
- SOLID não é respeitado
- A classe nesse pattern fere a responsabilidade única (SRP)
- Pois ela fica responsável pelo seu “motivo de criação”
- E pelo seu auto-gerenciamento, impedindo a criação de novas instâncias