Este é o primeiro do que deveria ser uma série bem longa sobre padrões de projetos de JavaScript. Em 1995, Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides (conhecidos como Gang of Four) publicaram ”Design Patterns: Elements of Reusable Object-Oriented Software”, um livro que catalogou soluções recorrentes para dilemas comuns em arquitetura de software e design. Ele também iniciou um vocabulário comum para se referir a essas soluções. Se quiser saber mais, você poderá encontrá-lo na Wikipedia.
O livro exemplifica implementações de cada uma das soluções escritas em C++ e Smalltalk, que são bastante diferentes do JavaScript. Outro livro – Pro JavaScript Design Patterns – foi escrito para trazer muitos desses padrões no contexto do JavaScript. Minha esperança é apresentar uma grande parte do conhecimento do livro aqui, mas não tanto que eu seja processado… Apenas o suficiente para mantê-lo interessado e, eventualmente, levá-lo a comprar o livro. Se comprar, informe-os que foi porque eu o recomendei a você. Talvez eles me forneçam um pouco de comissão (provavelmente não, mas tenho esperanças).
Totalmente sozinho com o Singleton
Em JavaScript, o singleton é extremamente simples e poderia ser excluído da designação de singleton, porém, tecnicamente, funciona de forma semelhante a um, por isso é ainda útil saber. Os grupos singleton se codificam em um único objeto, não sendo necessário iniciar um novo sempre que precisar de seus recursos, o que permite a você ter um acesso global a eles.
Em JavaScript, o singleton é utilizado principalmente para namespacing e para reduzir o número de variáveis globais que seu aplicativo cria. Esse padrão é provavelmente mais útil em JavaScript do que em qualquer outra linguagem, devido ao risco elevado do uso de variáveis globais em seu código e da capacidade do singleton para namespace essas variáveis.
Um Singleton básico
Este é a implementação do singleton em JavaScript mais básica e fácil de entender. É simplesmente um objeto literal com métodos e atributos, supostamente agrupados por algum tipo de relação que têm uns com os outros.
var Singleton = {
attr: 1,
another_attr: 'value',
method: function() {…},
another_method: function() {…}
};
Uma vez que é um objeto literal, ele não precisa ser instanciado e há, então, apenas uma cópia do mesmo. Isso permite o acesso a todos os métodos e os atributos de um único objeto global, como demonstrado abaixo:
Singleton.attr += 1;
Singleton.method();
…
JavaScript Namespacing
Um dos usos do padrão singleton em JavaScript é o Namespacing. Com linguagens como Java e C#, namespacing é construído dentro da linguagem e é necessário. A criação desses namespaces/pacotes organiza o código em blocos lógicos. Esse é um grande motivo para usar o padrão singleton em JavaScript, além do fato de que o uso de namespaces move o seu código a partir do contexto global para o novo singleton, levando a menos substituições acidentais e bugs.
O uso de um singleton para namespacing é bastante simples. Mais uma vez, você pode simplesmente criar um objeto literal:
var Namespace = {
Util: {
util_method1: function() {…},
util_method2: function() {…}
},
Ajax: {
ajax_method: function() {…}
},
some_method: function() {…}
};
Como pode ver, agora se você quiser usar um método utilitário, pode encontrá-lo em algum lugar sob namespace.util, como o que é mostrado no trecho seguinte. Claro que, como mostrado pela função some_method, os métodos não têm que ser enterrados em múltiplas camadas para o singleton.
Namespace.Util.util_method1();
Namespace.Ajax.ajax_method();
Namespace.some_method();
Normalmente, é possível ter todos esses métodos como funções globais, o que significa que há uma possibilidade muito maior de que serão substituídos, especialmente se for um nome tão simples como get, o que pode não ser de todo incomum. Você poderia ter namespacing um passo adiante e adicionar todas as suas variáveis e funções para esse singleton para diminuir mais as chances de seu código ser violado.
Página de código específico JavaScript
Em muitos casos, algumas páginas de um site executam códigos JavaScript diferentes de outras. Você pode usar a técnica namespacing singleton para encapsular a página de código específico e executá-lo quando a página terminar de ser carregada:
Namespace.homepage = {
init: function() {…},
method1: function() {…},
method2: function() {…}
}
Namespace.contactpage = {
init: function() {…},
method1: function() {…},
method2: function() {…}
}
Namespace.pageutil = {
getPageName: function() {
// somehow return the identifier for the current page
}
}
var pageName = Namespace.pageutil.getPageName();
window.onload = Namespace[pageName].init;
Isso pode ser muito útil para adicionar código para validar os diferentes formulários que aparecem em páginas distintas. Você pode até mesmo manter a funcionalidade que é usada em múltiplos formulários? em outra parte do namespace, como eu fiz com Namespace.pageutil.getPageName. Isso é um pouco diferente do que estava me referindo, porque o método getPageName não é usado realmente pelo código específico da página, mas sim para encontrar a referência ao código correto da página.
Mais com Pro JavaScript Design Patterns
O livro – Pro JavaScript Design Patterns – vai muito além do padrão singleton. Além do fato de ter comprimido seis páginas do livro para este artigo relativamente pequeno, ele abrange a criação de variáveis privadas pelo uso de closures, Lazy Instantiation, e Branching.
Como eu mencionei desde o início, não quero copiar muito o livro, pois quero instigar o seu interesse o suficiente para fazer com que queira comprá-lo, o que me beneficia tanto ajudando-os financeiramente, quanto persuadindo-os a não me processar . Sem mencionar que em um único artigo não abrange a mesma quantidade de material que um capítulo inteiro de um livro.
Se você achou útil ou simplesmente gostou do artigo, por favor, espalhe a palavra usando os botões de compartilhamento social. Caras de cidades pequenas como eu não ficam grandes sem uma ajuda de usuários como você. Obrigado!
?
Texto original disponível em http://www.joezimjs.com/javascript/javascript-design-patterns-singleton/