Pular para o conteúdo
GoF/23 Padrões de Projeto Criacionais
127
Criacional escopo de objeto

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
D

Definição

Intenção — palavra por palavra, como o livro define

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

E

Exemplo e motivação

Analogia

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.
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
D

Diagrama

Client AClient BSingleton- static instancia- constructor()+ static getInstance()getInstance()getInstance()retorna a si mesma
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.
A

Aplicabilidade

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.
C

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.
Apêndice

Código

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.
Apêndice

Relaçõ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.
Apêndice

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.