unity patrones patron example ejercicios ejemplos diseño code design-patterns

design patterns - patrones - ¿Cuándo debería usar el patrón singleton en lugar de una clase estática?



singleton c# example code (22)

Asigne un nombre a las consideraciones de diseño al decidir entre el uso de una clase singleton frente a una estática. Al hacer esto, te ves forzado a contrastar los dos, así que cualquier contraste que puedas encontrar también es útil para mostrar tu proceso de pensamiento. Además, a todos los entrevistadores les gusta ver ejemplos ilustrativos. :)


¿Qué tal "evitar ambos"? Singletons y clases estáticas:

  • Puede introducir estado global
  • Estrechamente unido a muchas otras clases
  • Ocultar dependencias
  • Puede dificultar el aislamiento de las clases de aislamiento

En cambio, busque en Inyección de dependencias e Inversión de bibliotecas de contenedores de control . Varias de las bibliotecas de IoC manejarán la administración de por vida para usted.

(Como siempre, hay excepciones, como las clases de matemática estática y los métodos de extensión de C #).


Creo que un lugar donde Singleton tendrá más sentido que la clase estática es cuando tienes que construir un grupo de recursos costosos (como conexiones de bases de datos). No le interesaría crear el grupo si nadie alguna vez lo usa (la clase estática significa que usted hace el trabajo costoso cuando se carga la clase).


Cuando la clase individual necesita estado. Singletons mantienen un estado global, las clases estáticas no.

Por ejemplo, hacer un ayudante alrededor de una clase de registro: si tiene una colmena que se puede cambiar (HKey Current User vs. HKEY Local Machine), puede ir:

RegistryEditor editor = RegistryEditor.GetInstance(); editor.Hive = LocalMachine

Ahora cualquier llamada adicional a ese singleton operará en la sección Local Machine. De lo contrario, utilizando una clase estática, debería especificar que la máquina local colgara cada cosa, o tener un método como ReadSubkeyFromLocalMachine .


El patrón de Singleton generalmente se usa para dar servicio a datos estáticos o independientes de la instancia donde múltiples hilos pueden acceder a los datos al mismo tiempo. Un ejemplo puede ser códigos de estado.


Las clases estáticas no se pueden pasar como argumentos; las instancias de un singleton pueden ser. Como se menciona en otras respuestas, observe los problemas de subprocesamiento con clases estáticas.

rp


Las clases estáticas se instancian en tiempo de ejecución. Esto podría llevar mucho tiempo. Singletons se pueden crear instancias solo cuando sea necesario.


Los Singletons no deben usarse de la misma manera que las clases estáticas. En esencia,

MyStaticClass.GetInstance().DoSomething();

es esencialmente lo mismo que

MyStaticClass.DoSomething();

Lo que realmente debería estar haciendo es tratar el singleton como un objeto más . Si un servicio requiere una instancia del tipo singleton, pase esa instancia al constructor:

var svc = new MyComplexServce(MyStaticClass.GetInstance());

El servicio no debe ser consciente de que el objeto es un singleton, y debe tratar el objeto como solo un objeto.

El objeto ciertamente se puede implementar, como un detalle de implementación y como un aspecto de la configuración general, como un singleton si eso facilita las cosas. Pero las cosas que usan el objeto no deberían tener que saber si el objeto es un singleton o no.


Los Singletons nunca deben usarse (a menos que considere que una clase sin estado mutable sea singleton). "clases estáticas" no deberían tener ningún estado mutable, salvo quizás cachés seguros para subprocesos y similares.

Casi cualquier ejemplo de singleton muestra cómo no hacerlo.


Los dos pueden ser bastante similares, pero recuerde que el verdadero Singleton debe ser instanciado (otorgado, una vez) y luego ser atendido. Una clase de base de datos PHP que devuelve una instancia de mysqli no es realmente un Singleton (como lo llaman algunas personas), porque devuelve una instancia de otra clase, no una instancia de la clase que tiene la instancia como miembro estático.

Entonces, si está escribiendo una nueva clase en la que planea permitir solo una instancia de en su código, también podría escribirla como Singleton. Piense en ello como escribir una clase de Java simple y agregarla para facilitar el requisito de instancia única. Si está utilizando la clase de otra persona que no puede modificar (como mysqli ), debe utilizar una clase estática (incluso si no puede prefijar su definición con la palabra clave).


Los singletons son más flexibles, lo que puede ser útil en los casos en los que desee que el método Instance devuelva diferentes subclases concretas del tipo Singleton basadas en algún contexto.


Piense en un singleton como un servicio. Es un objeto que proporciona un conjunto específico de funcionalidades. P.ej

ObjectFactory.getInstance().makeObject();

La fábrica de objetos es un objeto que realiza un servicio específico.

Por el contrario, una clase llena de métodos estáticos es una colección de acciones que puede desear realizar, organizadas en un grupo relacionado (La clase). P.ej

StringUtils.reverseString("Hello"); StringUtils.concat("Hello", "World");

El ejemplo de StringUtils aquí es una colección de funcionalidades que se puede aplicar en cualquier lugar. El objeto de fábrica singleton es un tipo específico de objeto con una responsabilidad clara que puede crearse y pasarse donde se requiera.


Si por "clase estática" te refieres a una clase que solo tiene variables estáticas, entonces en realidad pueden mantener el estado. Mi entendimiento es que la única diferencia sería cómo acceder a esto. Por ejemplo:

MySingleton().getInstance().doSomething();

versus

MySingleton.doSomething();

Las partes internas de MySingleton obviamente serán diferentes entre ellas pero, aparte de las cuestiones de seguridad de hilos, ambas realizarán lo mismo con respecto al código del cliente.


Si un singleton es algo que puede desechar, para limpiarlo después, puede considerarlo cuando es un recurso limitado (es decir, solo 1) que no necesita todo el tiempo, y tiene algún tipo de memoria o costo de recursos cuando se asigna.

El código de limpieza se ve más natural cuando tiene un singleton, a diferencia de una clase estática que contiene campos de estado estáticos.

El código, sin embargo, se verá igual en cualquier caso, así que si tiene más razones específicas para preguntar, quizás deba dar más detalles.


Singleton es como un servicio, como ya se mencionó. Pro es su flexibilidad. Estático, bueno, necesitas algunas partes estáticas para implementar Singleton.

Singleton tiene un código para encargarse de la instanciación del objeto real, lo que puede ser una gran ayuda si se encuentra con problemas de carreras. En una solución estática, es posible que tenga que lidiar con problemas de carreras en ubicaciones de códigos múltiples.

Sin embargo, al igual que Singleton se puede construir con algunas variables estáticas, es posible que pueda compararlo con ''goto''. Puede ser muy útil para construir otras estructuras, pero realmente necesita saber cómo usarlo y no debe "abusar" de él. Por lo tanto, la recomendación general es apegarse a Singleton y usar estática si es necesario.

también verifique la otra publicación: ¿Por qué elegir una clase estática sobre una implementación singleton?


Un singleton puede tener un constructor y un destructor. Dependiendo de su idioma, el constructor puede ser llamado automáticamente la primera vez que se utiliza su singleton, o nunca si su singleton no se utiliza en absoluto. Una clase estática no tendría tal inicialización automática.

Una vez que se obtiene una referencia a un objeto singleton, se puede usar como cualquier otro objeto. Es posible que el código del cliente ni siquiera necesite saber si está utilizando un singleton si una referencia al singleton se almacena anteriormente en:

Foo foo = Foo.getInstance(); doSomeWork(foo); // doSomeWork wont even know Foo is a singleton

Obviamente, esto facilita las cosas cuando elige deshacerse del patrón Singleton a favor de un patrón real, como IoC.


Un singleton también es una buena idea si desea forzar el almacenamiento en memoria caché eficiente de datos. por ejemplo, tengo una clase que busca definiciones en un documento xml. Como el análisis del documento puede llevar un tiempo, configuré un caché de definiciones (utilizo SoftReferences para evitar outOfmemeoryErrors). Si la definición deseada no está en la caché, realizo el costoso análisis xml. De lo contrario, devuelvo una copia del caché. Como tener múltiples cach significaría que aún tendría que cargar la misma definición varias veces, necesito tener un caché estático. Elijo implementar esta clase como singleton para poder escribir la clase utilizando solo miembros de datos normales (no estáticos). Esto me permite seguir creando una istantiation de la clase si la necesito por alguna razón (serialización, pruebas unitarias, etc.)


Una clase estática con una carga de variables estáticas es un poco un hack.

/** * Grotty static semaphore **/ public static class Ugly { private static int count; public synchronized static void increment(){ count++; } public synchronized static void decrement(){ count--; if( count<0 ) { count=0; } } public synchronized static boolean isClear(){ return count==0; } }

Un singleton con una instancia real es mejor.

/** * Grotty static semaphore **/ public static class LessUgly { private static LessUgly instance; private int count; private LessUgly(){ } public static synchronized getInstance(){ if( instance==null){ instance = new LessUgly(); } return instance; } public synchronized void increment(){ count++; } public synchronized void decrement(){ count--; if( count<0 ) { count=0; } } public synchronized boolean isClear(){ return count==0; } }

El estado está SOLAMENTE en la instancia.

Por lo tanto, el singleton se puede modificar más adelante para hacer agrupaciones, instancias de subprocesos locales, etc. Y ninguno de los códigos ya escritos debe cambiar para obtener el beneficio.

public static class LessUgly { private static Hashtable<String,LessUgly> session; private static FIFO<LessUgly> freePool = new FIFO<LessUgly>(); private static final POOL_SIZE=5; private int count; private LessUgly(){ } public static synchronized getInstance(){ if( session==null){ session = new Hashtable<String,LessUgly>(POOL_SIZE); for( int i=0; i < POOL_SIZE; i++){ LessUgly instance = new LessUgly(); freePool.add( instance) } } LessUgly instance = session.get( Session.getSessionID()); if( instance == null){ instance = freePool.read(); } if( instance==null){ // TODO search sessions for expired ones. Return spares to the freePool. //FIXME took too long to write example in blog editor. } return instance; }

Es posible hacer algo similar con una clase estática, pero habrá una sobrecarga por llamada en el despacho indirecto.

Puede obtener la instancia y pasarla a una función como argumento. Esto permite que el código se dirija al singleton "derecho". Sabemos que solo necesitarás uno ... hasta que no lo hagas.

El gran beneficio es que los singleton con estado se pueden convertir en hilos seguros, mientras que una clase estática no puede hacerlo, a menos que lo modifique para que sea un singleton secreto.


Una de mis discusiones favoritas sobre este tema es here (sitio original inactivo, ahora vinculado a Internet Archive Wayback Machine ).

Para resumir las ventajas de flexibilidad de Singleton:

  • un Singleton se puede convertir fácilmente en una fábrica
  • un Singleton se puede modificar fácilmente para devolver diferentes subclases
  • esto puede dar como resultado una aplicación más fácil de mantener

Utilice el patrón de singleton cuando necesite calcular algo en tiempo de ejecución que podría calcular en tiempo de compilación si pudiera, como tablas de búsqueda.


Yo diría que la única diferencia es la sintaxis: MySingleton.Current.Whatever () vs MySingleton.Whatever (). El estado, como David mencionó, es en última instancia "estático" en cualquier caso.

EDITAR: La brigada del enterramiento vino de digg ... de todos modos, pensé en un caso que requeriría un singleton. Las clases estáticas no pueden heredar de una clase base ni implementar una interfaz (al menos en .Net no pueden). Entonces, si necesita esta funcionalidad, debe usar un singleton.


referir codeofdoom.com/wordpress/2008/04/20/…

resumen:

a. Una regla fácil que puede seguir es si no necesita mantener el estado, puede usar una clase estática; de lo contrario, debería usar un Singleton.

segundo. usar un Singleton es si es un objeto particularmente "pesado". Si su objeto es grande y ocupa una cantidad razonable de memoria, muchas llamadas n / w (grupo de conexiones) ... etc. Para asegurarse de que no se va a instanciar varias veces. Una clase de Singleton ayudará a evitar que el caso suceda


  • Singletons puede implementar interfaces y heredar de otras clases.
  • Los Singletons pueden cargarse de forma lenta. Solo cuando realmente se necesita. Eso es muy útil si la inicialización incluye una costosa carga de recursos o conexiones de bases de datos.
  • Singletons ofrece un objeto real.
  • Singletons se puede extender a una fábrica. La gestión de objetos detrás de escena es abstracta, por lo que es mejor mantenerla y da como resultado un mejor código.