Pular para o conteúdo
GoF Padrões de Projeto Criacionais
Criacional escopo de objeto
GoF, p. 127

Singleton

Singleton

Uma única instância na aplicação inteira, com ponto de acesso global.

Complexidade simples Frequência de uso moderada padrão controverso
Intençãocomo o livro define

Garantir que uma classe tenha somente uma instância e fornecer um ponto global de acesso a ela.

Analogiauma imagem do mundo real

O governo de um país

Um país tem um único governo oficial. Independentemente de quem sejam as pessoas nos cargos, “o Governo do Brasil” é um ponto de acesso global a uma entidade única. Você não instancia um segundo governo — você pede o que já existe.

O problema

Dois problemas ao mesmo tempo (e é por isso que o padrão é criticado): garantir instância única de um recurso compartilhado (uma conexão, um cache) e oferecer acesso global a ele. Uma variável global resolveria o acesso, mas qualquer código poderia sobrescrevê-la.

A solução

Torne o construtor privado e exponha um método estático que cria a instância na primeira chamada e devolve a mesma daí em diante.

Sintomascomo reconhecer no seu código
  • Testes que passam sozinhos e falham em suíte (estado vazando pelo singleton).
  • Algo.getInstance() no meio de uma regra de negócio.

Estrutura

getInstance()getInstance()retorna a si mesmaClient AClient BSingleton- static instancia- constructor()+ static getInstance()
Fig. 5 — Singleton herda / implementa cria usa / contém
Ver este diagrama sendo desenhado, traço a traço
Participantes
Singleton
Guarda a instância única em campo estático e expõe `getInstance()`; construtor privado.

Implementação

Listagem 5 Configuração da aplicação carregada uma única vez
class Configuracao {
  static #instancia = null;
  #valores;

  constructor() {
    if (Configuracao.#instancia) {
      throw new Error('Use Configuracao.getInstance()');
    }
    // Inicialização cara: só acontece uma vez na vida do processo.
    this.#valores = { api: 'https://api.exemplo.com', timeout: 5000, debug: false };
    console.log('⚙️  configuração carregada (uma única vez)');
  }

  static getInstance() {
    // Inicialização preguiçosa: só cria quando alguém realmente precisa.
    if (!Configuracao.#instancia) Configuracao.#instancia = new Configuracao();
    return Configuracao.#instancia;
  }

  get(chave) { return this.#valores[chave]; }
  set(chave, valor) { this.#valores[chave] = valor; }
}

const a = Configuracao.getInstance();
const b = Configuracao.getInstance();
console.log(a === b);            // true — é o MESMO objeto
a.set('debug', true);
console.log(b.get('debug'));     // true — estado compartilhado

// ⚠️ Em JavaScript com módulos ES, este é o Singleton idiomático:
//    export default new Configuracao();
//    O sistema de módulos já garante que o módulo é avaliado uma única vez.
Na práticaonde ele já existe
  • java.lang.Runtime.getRuntime()
  • java.awt.Desktop.getDesktop()
  • O objeto `window` / `console` do navegador
  • Containers de DI geralmente registram serviços como singletons — sem o padrão GoF

Consequências

A favor
  • Garante instância única de verdade.
  • Ponto de acesso global bem definido.
  • Inicialização preguiçosa: só paga o custo quando alguém usa.
Contra
  • Viola o Princípio da Responsabilidade Única: resolve unicidade E acesso global.
  • Esconde dependências — a classe que o usa não declara que depende dele.
  • Dificulta testes: não dá para injetar um dublê facilmente, e o estado vaza entre testes.
  • Exige tratamento especial em ambientes multithread.
  • É, na prática, uma variável global com um disfarce elegante.
Use quando
  • Existe um recurso genuinamente único e compartilhado (pool de conexões, logger, cache de processo).
  • Você precisa de controle estrito sobre variáveis globais que já existiriam de qualquer jeito.
Evite quando
  • Você só quer “acessar de qualquer lugar” — prefira injeção de dependência.
  • O objeto tem estado mutável relevante para o negócio (pesadelo em testes e concorrência).
  • Você está numa aplicação multi-tenant ou serverless onde “único por processo” é a granularidade errada.

Relações com outros padrões

costuma andar junto
Abstract Factory
Fábricas e Directors costumam ser Singletons.
Facade
Uma Facade normalmente basta como Singleton.
parecido / fácil de confundir
Flyweight
Ambos economizam instâncias; Flyweight tem MUITAS instâncias imutáveis, Singleton tem UMA mutável.
alternativa a
Prototype
Quando o que você quer é um objeto pré-configurado (e não único), clonar um protótipo costuma ser melhor. Fora do catálogo GoF, a alternativa moderna é injeção de dependência com escopo singleton no container.

Verificação

Questãoa resposta está marcada

Qual é a crítica mais forte ao Singleton?

  1. Ele acopla o código a um estado global e esconde dependências, prejudicando testes
  2. Ele consome mais memória que criar várias instâncias
  3. Ele não funciona em linguagens orientadas a objetos modernas
  4. Ele impede o uso de herança em qualquer parte do sistema

O custo real não é memória, é design: quem chama `getInstance()` não declara essa dependência na assinatura, e o estado global compartilhado torna testes frágeis. Injeção de dependência costuma ser a resposta melhor.