Go to English Blog

Design Patterns no JavaScript – Singleton

Leia em 1 minuto

No artigo anterior vimos como funciona o Module Pattern. Agora chegou a hora de vermos um pouco sobre o Singleton Pattern.

O Singleton Pattern diz que você pode ter apenas uma única instância de uma classe (ou, no caso do JavaScript, função construtora). Isso significa que uma vez que a classe for instanciada, você deve sempre retornar esta mesma instância em chamadas subsequentes.

Um exemplo clássico deste pattern é usar um único objeto como namespace de sua aplicação.

var HOWTO = {};

Pelo fato de termos definido a variável como um objeto, não podemos instanciar novos objetos à partir dele (embora possamos criar novos objetos usando este como base com a função Object.create, por exemplo).

Esse pattern também pode ser aplicado às funções construtoras. A maneira mais simples é utilizar Singleton com Immediately-Invoked Function Expression (IIFE) ou, como dizemos mais comumente, funções auto-executáveis.

function MyApp() {
  if (!MyApp.instance) {
    MyApp.instance = this;
  }

  return MyApp.instance;
}

Essa função construtora irá garantir que você sempre receba a mesma instância como resultado. Isso só é possível porque funções construtoras utilizam o retorno como resultado da instanciação. Na prática, você poderia retornar qualquer tipo de objeto, como arrays ou strings.

var instance = new MyApp();
console.log(instance === new MyApp());
//=> true

Você pode perceber que o resultado é sempre o mesmo, independente de quantas vezes instanciarmos a função MyApp.

O grande problema dessa implementação é que alguém pode manipular a instância armazenada em MyApp.instance, embora seja pouco provável. Uma alternativa seria utilizar o conceito de closure para simular a privacidade do atributo.

function MyApp() {
  var instance;

  // Override the original implementation.
  MyApp = function() {
    return instance;
  };

  // Set the instance.
  instance = this;
}

Essa é uma implementação bastante curiosa. A função MyApp possui uma implementação que redefine a própria função MyApp para retornar apenas a instância.

Alternativamente você poderia utilizar o Module Pattern, mas acho que fica um pouco mais complexo que a implementação anterior.

var MyApp;

(function(){
  var instance;

  MyApp = function() {
    if (instance) {
      return instance;
    }

    instance = this;
  };
})();

Finalizando

Sempre que quiser garantir a existência de apenas uma instância de uma função construtora, por exemplo, utilize o Singleton Pattern.

No próximo artigo iremos falar sobre o Factory Pattern.