Qual é a maneira mais simples / limpa de implementar o padrão singleton em JavaScript?
javascript
function
design-patterns
singleton
Jakub Arnold
fonte
fonte
Respostas:
Eu acho que a maneira mais fácil é declarar um simples objeto literal:
Se você deseja membros privados em sua instância singleton, pode fazer algo assim:
Isto tem sido chamado o padrão de módulo , que basicamente permite que você encapsular membros privados em um objeto, aproveitando-se o uso de fechamentos .
UPDATE: Gostaria de acrescentar que, se você quiser impedir a modificação do objeto singleton, poderá congelá-lo usando o ES5
Object.freeze
método .Isso tornará o objeto imutável, impedindo qualquer modificação em sua estrutura e valores.
Além disso, gostaria de mencionar que, se você estiver usando o ES6, poderá representar um singleton usando os Módulos do ES com muita facilidade e pode manter um estado privado declarando variáveis no escopo do módulo :
Então você pode simplesmente importar o objeto singleton para usá-lo:
fonte
publicMethod1
chamariapublicMethod2
?getInstance
método estático e um construtor privado -, mas IMO, essa é a maneira mais "simples" de criar um objeto singleton em Javascript, e no final ele atende ao mesmo objetivo - um único objeto, que você não pode inicializar novamente (não há construtor, é apenas um objeto) -. Sobre o código vinculado, ele tem alguns problemas, trocar asa
eb
variável declarações e testea === window
. Felicidades.Eu acho que a abordagem mais limpa é algo como:
Depois, você pode chamar a função como
fonte
delete instance.constructor
:x = SingletonClass.getInstance();delete x.constructor;new x.constructor;
Não tenho certeza se concordo com o padrão do módulo sendo usado como substituto de um padrão singleton. Eu sempre vi singletons usados e abusados em lugares onde eles são totalmente desnecessários, e tenho certeza que o padrão do módulo preenche muitas lacunas onde os programadores usariam um singleton, mas o padrão do módulo não é um singleton.
padrão do módulo:
Tudo inicializado no padrão do módulo acontece quando
Foo
é declarado. Além disso, o padrão do módulo pode ser usado para inicializar um construtor, que pode ser instanciado várias vezes. Embora o padrão do módulo seja a ferramenta certa para muitos trabalhos, não é equivalente a um singleton.padrão singleton:
forma curta formato longo, usando o padrão do móduloNas duas versões do padrão Singleton que eu forneci, o próprio construtor pode ser usado como o acessador:
Se você não se sentir confortável usando o construtor dessa maneira, poderá gerar um erro na
if (instance)
instrução e continuar usando o formulário longo:Também devo mencionar que o padrão singleton se ajusta bem ao padrão implícito da função construtora:
fonte
var singleton = {}
não se encaixa nessa definição.var singleton = {}
é como você implementa o singleton em Javascript .Em
es6
:fonte
instance
campo. Como está atualmente (instance
definida comothis
), essa classe também pode ter outros campos e o congelamento não faz sentido.O seguinte funciona no nó v6
Testamos:
fonte
No ES6, a maneira correta de fazer isso é:
Ou, se você não deseja que um erro seja gerado na criação da segunda instância, basta retornar a última instância, assim:
fonte
instance
e_instance
. É apenas uma convenção de nomenclatura nas linguagens de programação que denominamos variáveis privadas anexadas com um sublinhado. Eu suspeito que a razão para o seu código não funcionar é que você está usando emthis.instance
vez deMyClass.instance
Existem mais de uma maneira de esfolar um gato :) Dependendo do seu gosto ou necessidade específica, você pode aplicar qualquer uma das soluções propostas. Pessoalmente, busco a primeira solução do CMS sempre que possível (quando você não precisa de privacidade). Como a pergunta era sobre a mais simples e a mais limpa, esse é o vencedor. Ou até:
Isso (citação do meu blog) ...
não faz muito sentido (o exemplo do meu blog também não) porque não precisa de vars particulares, portanto é praticamente o mesmo que:
fonte
this.f(){}
Eu reprovo minha resposta, vejo minha outra .
Normalmente, o padrão do módulo (consulte a resposta do CMS), que NÃO é padrão singleton, é bom o suficiente. No entanto, um dos recursos do singleton é que sua inicialização é atrasada até que o objeto seja necessário. O padrão do módulo não possui esse recurso.
Minha proposta (CoffeeScript):
O que foi compilado em JavaScript:
Então eu posso fazer o seguinte:
fonte
Resposta curta:
Devido à natureza não-bloqueadora do JavaScript, Singletons em JavaScript são realmente feios em uso. As variáveis globais também fornecerão uma instância por todo o aplicativo, sem todos esses retornos de chamada; o padrão do módulo oculta suavemente os internos por trás da interface. Consulte a resposta @CMS.
Mas, desde que você queria um singleton ...
Uso:
Explicação:
Os singletons oferecem mais do que apenas uma instância em todo o aplicativo: a inicialização é adiada até o primeiro uso. Isso é realmente importante quando você lida com objetos cuja inicialização é cara. Caro geralmente significa E / S e, em JavaScript, E / S sempre significam retornos de chamada.
Não confie em respostas que lhe dão uma interface
instance = singleton.getInstance()
, pois todas elas não entendem.Se eles não aceitarem que o retorno de chamada seja executado quando a instância estiver pronta, eles não funcionarão quando o inicializador fizer E / S.
Sim, os retornos de chamada sempre parecem mais feios que a chamada de função, que retorna imediatamente a instância do objeto. Mas, novamente: quando você faz E / S, os retornos de chamada são obrigatórios. Se você não deseja fazer nenhuma E / S, a instanciação é barata o suficiente para fazê-lo no início do programa.
Exemplo 1, inicializador barato:
Exemplo 2, inicialização com E / S:
Neste exemplo,
setTimeout
falsifica algumas operações caras de E / S. Isso ilustra por que os singletons em JavaScript realmente precisam de retornos de chamada.fonte
Eu peguei este exemplo no JavaScript Patterns Crie aplicativos melhores com padrões de codificação e design Pelo livro de Stoyan Stefanov , caso você precise de uma classe de implementação simples, como o objeto singltone, use a função imediata da seguinte maneira:
E você pode verificar este exemplo seguindo o caso de teste:
Essa abordagem passa em todos os casos de teste, enquanto a implementação estática privada falha quando a extensão do protótipo é usada (pode ser corrigida, mas não será simples), e a implementação estática pública menos aconselhável, porque a instância é exposta ao público.
Demonstração do jsFiddly.
fonte
Acho que encontrei a maneira mais limpa de programar em JavaScript, mas você precisará de imaginação. Eu recebi essa idéia de uma técnica de trabalho no livro "javascript the good parts".
Em vez de usar a nova palavra-chave, você pode criar uma classe como esta:
Você pode instanciar o objeto acima dizendo:
Agora, com este método de trabalho em mente, você pode criar um singleton como este:
Agora você pode obter sua instância chamando
Eu acho que essa é a maneira mais legal, pois a "Classe" completa nem sequer é acessível.
fonte
O @CMS e o @zzzzBov deram respostas maravilhosas, mas apenas para adicionar minha própria interpretação, com base na minha mudança para o desenvolvimento node.js pesado do PHP / Zend Framework, onde os padrões singleton eram comuns.
O seguinte código documentado para comentários é baseado nos seguintes requisitos:
Meu código é muito semelhante ao do @ zzzzBov, exceto que eu adicionei uma cadeia de protótipos ao construtor e mais comentários que devem ajudar os que vêm do PHP ou de uma linguagem semelhante a traduzir a natureza prototípica do OOP tradicional para Javascripts. Pode não ser o "mais simples", mas acredito que seja o mais adequado.
Observe que tecnicamente, a função anônima de execução automática é, ela própria, um Singleton, conforme demonstrado com agrado no código fornecido pelo @CMS. O único problema aqui é que não é possível modificar a cadeia de protótipos do construtor quando o próprio construtor é anônimo.
Lembre-se de que, para Javascript, os conceitos de "público" e "privado" não se aplicam como em PHP ou Java. Mas alcançamos o mesmo efeito, aproveitando as regras de disponibilidade de escopo funcional do Javascript.
fonte
var a = Singleton.getInstance('foo'); var b = new a.constructor('bar');
Não sei por que ninguém trouxe isso à tona, mas você pode fazer:
fonte
A resposta mais clara deve ser essa do livro Learning JavaScript Design Patterns de Addy Osmani.
fonte
Acredito que esta é a maneira mais simples / limpa e mais intuitiva, embora exija ES7:
O código fonte é de: adam-bien.com
fonte
new Singleton()
O que há de errado nisso?
fonte
Test = Klass; t1 = new Test(); t2 = new Test();
- sem oportunidade de renomear a classe ou escolher um espaço para nome diferente.posso colocar minhas 5 moedas? Eu tenho uma função construtora, ex.
O que eu preciso fazer é que todos os objetos criados por esse CF sejam iguais.
teste
fonte
Eu achei o seguinte o padrão Singleton mais fácil, porque o uso do novo operador torna isso imediatamente disponível na função, eliminando a necessidade de retornar um literal de objeto:
fonte
Aqui está o exemplo simples para explicar o padrão singleton em javascript.
fonte
Eu precisava de vários singletons com:
e foi assim que eu inventei:
args deve ser Array para que isso funcione; se você tiver variáveis vazias, basta passar []
Usei o objeto window na função, mas poderia ter passado um parâmetro para criar meu próprio escopo
Os parâmetros name e construct são apenas String para que window [] funcione, mas com algumas verificações simples, window.name e window.construct também são possíveis.
fonte
Que tal dessa maneira, apenas garantir que a classe não possa ser nova novamente.
Por isso, você pode usar o
instanceof
op, também, você pode usar a cadeia de protótipos para herdar a classe, é uma classe regular, mas não pode ser nova, se você deseja obter a instância, basta usargetInstance
Se você não deseja expor o
instance
membro, basta encerrá-lo.fonte
A seguir, é apresentado o trecho do meu percurso para implementar um padrão singleton. Isso me ocorreu durante um processo de entrevista e achei que deveria capturar isso em algum lugar.
o mesmo pode ser encontrado em minha essência página
fonte
fonte
Isso não é um singleton também?
fonte
Você pode fazer isso com decoradores, como neste exemplo abaixo, para TypeScript:
Então você usa seu singleton assim:
No momento da redação deste artigo, os decoradores não estão prontamente disponíveis nos mecanismos JavaScript. Você precisa garantir que o tempo de execução do JavaScript tenha os decoradores realmente ativados ou use compiladores como Babel e TypeScript.
Observe também que a instância singleton é criada "preguiçosa", ou seja, é criada somente quando você a utiliza pela primeira vez.
fonte
Padrão do módulo: no "estilo mais legível". Você pode ver facilmente quais métodos são públicos e quais são privados
agora você pode usar métodos públicos como
module.method2 (); // -> Estou chamando um método privado por um alerta de método público ("oi, sou um método privado")
http://jsfiddle.net/ncubica/xMwS9/
fonte
Singleton:
Garanta que uma classe tenha apenas uma instância e forneça um ponto de acesso global a ela.
O Padrão Singleton limita o número de instâncias de um objeto específico a apenas uma. Essa instância única é chamada de singleton.
O objeto Singleton é implementado como uma função anônima imediata. A função é executada imediatamente envolvendo-a entre colchetes, seguida por dois colchetes adicionais. É chamado anônimo porque não tem nome.
Programa de amostra,
fonte
Mais simples / mais limpo para mim significa também simplesmente entender e não há sinos e assobios, como são discutidos na versão Java da discussão:
O que é uma maneira eficiente de implementar um padrão singleton em Java?
A resposta que se encaixaria melhor / mais limpa do meu ponto de vista é:
https://stackoverflow.com/a/70824/1497139
E só pode ser traduzido parcialmente para JavaScript. Algumas das diferenças em Javascript são:
Mas, dada a sintaxe mais recente da ECMA, é possível se aproximar de:
Padrão Singleton como exemplo de classe JavaScript
Exemplo de uso
Resultado de exemplo
fonte
Se você estiver em aulas:
Teste:
fonte
Se você deseja usar classes:
A saída para o acima será:
Outra maneira de escrever Singleton usando a função
A saída para o acima será:
fonte