¿Cuál es la forma más simple / limpia de implementar un patrón singleton en JavaScript?
javascript
function
design-patterns
singleton
Jakub Arnold
fuente
fuente
Respuestas:
Creo que la forma más fácil es declarar un objeto literal simple:
Si desea miembros privados en su instancia de singleton, puede hacer algo como esto:
Esto ha sido llamado el patrón de módulo , que básicamente le permite encapsular los miembros privados en un objeto, mediante el aprovechamiento de la utilización de cierres .
ACTUALIZACIÓN: Me gustaría agregar que si desea evitar la modificación del objeto singleton, puede congelarlo , utilizando el
Object.freeze
método ES5 .Eso hará que el objeto sea inmutable, evitando cualquier modificación en su estructura y valores.
Además, me gustaría mencionar que si está utilizando ES6, puede representar un singleton utilizando módulos ES muy fácilmente, e incluso puede mantener el estado privado declarando variables en el alcance del módulo :
Luego, simplemente puede importar el objeto singleton para usarlo:
fuente
publicMethod1
llamaríapublicMethod2
?getInstance
método estático y un constructor privado-, pero en mi opinión, esta es la forma más "simple" de construir un objeto singleton en Javascript, y al final cumple el mismo propósito -un objeto único, que no puede inicializar nuevamente (no hay constructor, es solo un objeto) -. Sobre el código se ha vinculado, tiene algunos problemas, intercambiar losa
yb
las declaraciones de variables y pruebaa === window
. Salud.Creo que el enfoque más limpio es algo como:
Luego, puede invocar la función como
fuente
delete instance.constructor
:x = SingletonClass.getInstance();delete x.constructor;new x.constructor;
No estoy seguro de estar de acuerdo con el patrón del módulo que se utiliza como reemplazo de un patrón singleton. A menudo he visto los singletons utilizados y abusados en lugares donde son totalmente innecesarios, y estoy seguro de que el patrón del módulo llena muchos vacíos donde los programadores usarían un singleton, sin embargo, el patrón del módulo no es un singleton.
patrón de módulo:
Todo lo que se inicializa en el patrón del módulo ocurre cuando
Foo
se declara. Además, el patrón del módulo se puede usar para inicializar un constructor, que luego se puede instanciar varias veces. Si bien el patrón del módulo es la herramienta adecuada para muchos trabajos, no es equivalente a un singleton.patrón singleton:
forma corta forma larga, usando patrón de móduloEn ambas versiones del patrón Singleton que he proporcionado, el propio constructor puede usarse como el descriptor de acceso:
Si no se siente cómodo usando el constructor de esta manera, puede arrojar un error en la
if (instance)
declaración y seguir usando la forma larga:También debo mencionar que el patrón singleton encaja bien con el patrón de función de constructor implícito:
fuente
var singleton = {}
no se ajusta a esa definición.var singleton = {}
es cómo implementar singleton en Javascript .En
es6
:fuente
instance
campo. Como está actualmente (instance
configurado enthis
), esta clase también puede tener otros campos y congelar no tiene sentido.Lo siguiente funciona en el nodo v6
Probamos:
fuente
En ES6, la forma correcta de hacer esto es:
O, si no desea que se genere un error en la creación de la segunda instancia, simplemente puede devolver la última instancia, de esta manera:
fuente
instance
y_instance
. Es solo una convención de nomenclatura en lenguajes de programación que nombramos variables privadas antepuestas con un guión bajo. Sospecho que la razón de que su código no funcione es que está usando enthis.instance
lugar deMyClass.instance
Hay más de una forma de pelar un gato :) Dependiendo de su gusto o necesidad específica, puede aplicar cualquiera de las soluciones propuestas. Yo personalmente busco la primera solución de CMS siempre que sea posible (cuando no necesita privacidad). Como la pregunta era sobre la más simple y limpia, esa es la ganadora. O incluso:
Esto (cita de mi blog) ...
no tiene mucho sentido (mi ejemplo de blog tampoco) porque no necesita ninguna variable privada, por lo que es casi lo mismo que:
fuente
this.f(){}
Deprecio mi respuesta, veo la otra .
Por lo general, el patrón de módulo (consulte la respuesta de CMS) que NO es un patrón único es lo suficientemente bueno. Sin embargo, una de las características de singleton es que su inicialización se retrasa hasta que se necesita un objeto. El patrón del módulo carece de esta característica.
Mi propuesta (CoffeeScript):
Que compiló esto en JavaScript:
Entonces puedo hacer lo siguiente:
fuente
Respuesta corta:
Debido a la naturaleza no bloqueante de JavaScript, los Singletons en JavaScript son realmente feos en uso. Las variables globales también le darán una instancia a través de toda la aplicación sin todas estas devoluciones de llamada, el patrón del módulo oculta suavemente las partes internas detrás de la interfaz. Ver la respuesta de @CMS.
Pero, como querías un singleton ...
Uso:
Explicación:
Los Singletons le brindan más de una instancia a través de toda la aplicación: su inicialización se retrasa hasta el primer uso. Esto es realmente importante cuando se trata de objetos cuya inicialización es costosa. Caro generalmente significa E / S y en JavaScript E / S siempre significa devoluciones de llamada.
No confíes en las respuestas que te dan una interfaz como
instance = singleton.getInstance()
, todas pierden el punto.Si no toman la devolución de llamada para ejecutarse cuando la instancia está lista, entonces no funcionarán cuando el inicializador haga E / S.
Sí, las devoluciones de llamada siempre se ven más feas que la llamada a la función, que devuelve inmediatamente la instancia del objeto. Pero de nuevo: cuando haces E / S, las devoluciones de llamada son obligatorias. Si no desea hacer ninguna E / S, la creación de instancias es lo suficientemente barata como para hacerlo al inicio del programa.
Ejemplo 1, inicializador barato:
Ejemplo 2, inicialización con E / S:
En este ejemplo,
setTimeout
simula algunas operaciones costosas de E / S. Esto ilustra por qué los singletons en JavaScript realmente necesitan devoluciones de llamada.fuente
Obtuve este ejemplo de Patrones de JavaScript Construir mejores aplicaciones con codificación y patrones de diseño Por el libro de Stoyan Stefanov en caso de que necesite alguna clase de implementación simple como un objeto singltone, puede usar la función inmediata de la siguiente manera:
Y puede consultar este ejemplo siguiendo el caso de prueba:
Este enfoque supera todos los casos de prueba, mientras que la implementación estática privada fallará cuando se use la extensión del prototipo (se puede arreglar, pero no será simple) y la implementación estática pública es menos aconsejable debido a que la instancia está expuesta al público.
jsFiddly demo.
fuente
Creo que he encontrado la forma más limpia de programar en JavaScript, pero necesitarás algo de imaginación. Obtuve esta idea de una técnica de trabajo en el libro "javascript las partes buenas".
En lugar de usar la nueva palabra clave, puede crear una clase como esta:
Puede crear una instancia del objeto anterior diciendo:
Ahora, con este método de trabajo en mente, podría crear un singleton como este:
Ahora puede obtener su instancia llamando
Creo que esta es la mejor manera ya que ni siquiera se puede acceder a la "Clase" completa.
fuente
@CMS y @zzzzBov han dado respuestas maravillosas, pero solo para agregar mi propia interpretación basada en que me mudé al desarrollo de node.js pesado desde PHP / Zend Framework, donde los patrones singleton eran comunes.
El siguiente código documentado con comentarios se basa en los siguientes requisitos:
Mi código es muy similar al de @ zzzzBov, excepto que he agregado una cadena de prototipo al constructor y más comentarios que deberían ayudar a aquellos que provienen de PHP o un lenguaje similar a traducir OOP tradicional a la naturaleza prototípica de Javascripts. Puede que no sea el "más simple" pero creo que es el más apropiado.
Tenga en cuenta que, técnicamente, la función anónima de ejecución automática es en sí misma un Singleton, como se demuestra muy bien en el código proporcionado por @CMS. El único inconveniente aquí es que no es posible modificar la cadena de prototipo del constructor cuando el constructor en sí es anónimo.
Tenga en cuenta que para Javascript, los conceptos de "público" y "privado" no se aplican como lo hacen en PHP o Java. Pero hemos logrado el mismo efecto al aprovechar las reglas de disponibilidad de alcance funcional de Javascript.
fuente
var a = Singleton.getInstance('foo'); var b = new a.constructor('bar');
No estoy seguro de por qué nadie mencionó esto, pero podrías hacer lo siguiente:
fuente
La respuesta más clara debería ser esta del libro Learning JavaScript Design Patterns de Addy Osmani.
fuente
Creo que esta es la forma más simple / limpia e intuitiva, aunque requiere ES7:
El código fuente es de: adam-bien.com
fuente
new Singleton()
¿Qué tiene de malo esto?
fuente
Test = Klass; t1 = new Test(); t2 = new Test();
- no hay oportunidad de cambiar el nombre de la clase o elegir un espacio de nombres diferente.¿Puedo poner mis 5 monedas? Tengo una función constructora, ej.
Lo que necesito hacer es que cada objeto creado por este CF será el mismo.
prueba
fuente
He encontrado que lo siguiente es el patrón más fácil Singleton, porque el uso de la nueva operador hace que esta inmediatamente disponible dentro de la función, lo que elimina la necesidad de devolver un objeto literal:
fuente
Aquí está el ejemplo simple para explicar el patrón singleton en javascript.
fuente
Necesitaba varios singletons con:
y esto fue lo que se me ocurrió:
los argumentos deben ser Array para que esto funcione, así que si tiene variables vacías, simplemente pase []
Utilicé un objeto de ventana en la función, pero podría haber pasado un parámetro para crear mi propio alcance
los parámetros de nombre y construcción son solo String para que la ventana [] funcione, pero con algunas verificaciones de tipo simples, window.name y window.construct también son posibles.
fuente
¿Qué tal esta manera? Solo asegúrate de que la clase no pueda volver a empezar.
Con esto, puede usar el
instanceof
op, también, puede usar la cadena de prototipo para heredar la clase, es una clase regular, pero no puede ser nueva, si desea obtener la instancia simplemente usegetInstance
Si no desea exponer al
instance
miembro, solo ciérrelo.fuente
El siguiente es el fragmento de mi recorrido para implementar un patrón singleton. Esto se me ocurrió durante un proceso de entrevista y sentí que debería capturar esto en alguna parte.
lo mismo se puede conocer en mi GIST página
fuente
fuente
¿No es esto un singleton también?
fuente
Puede hacerlo con decoradores como en este ejemplo a continuación para TypeScript:
Luego usas tu singleton así:
Al escribir estas líneas, los decoradores no están disponibles en los motores de JavaScript. Debería asegurarse de que su tiempo de ejecución de JavaScript tenga decoradores realmente habilitados o usar compiladores como Babel y TypeScript.
También tenga en cuenta que la instancia de singleton se crea "perezosa", es decir, se crea solo cuando la usa por primera vez.
fuente
Patrón de módulo: en "estilo más legible". Puede ver fácilmente qué métodos son públicos y cuáles son privados
ahora puedes usar métodos públicos como
module.method2 (); // -> Estoy llamando a un método privado a través de una alerta de método público ("hola soy un método privado")
http://jsfiddle.net/ncubica/xMwS9/
fuente
Único:
Asegúrese de que una clase tenga solo una instancia y proporcione un punto de acceso global.
El patrón Singleton limita el número de instancias de un objeto en particular a solo uno. Esta instancia única se llama singleton.
El objeto Singleton se implementa como una función anónima inmediata. La función se ejecuta inmediatamente envolviéndola entre paréntesis seguido de dos corchetes adicionales. Se llama anónimo porque no tiene nombre.
Programa de muestra,
fuente
Más simple / más limpio para mí significa también simplemente entender y sin campanas ni silbidos como se discute mucho en la versión Java de la discusión:
¿Cuál es una manera eficiente de implementar un patrón singleton en Java?
La respuesta que encajaría mejor desde el punto de vista más simple / más limpio es:
https://stackoverflow.com/a/70824/1497139
Y solo se puede traducir parcialmente a JavaScript. Algunas de las diferencias en Javascript son:
Pero dada la última sintaxis de ECMA, es posible acercarse a:
Patrón Singleton como ejemplo de clase JavaScript
Ejemplo de uso
Resultado de ejemplo
fuente
Si estás en clases:
Prueba:
fuente
Si quieres usar clases:
La salida para lo anterior será:
Otra forma de escribir Singleton usando la función
La salida para lo anterior será:
fuente