Creo que este post le servidrá más a los muchachos de 1ero o 2do años que probablemente aún no conocen los patrones de diseño y que quizás no han encontrado la manera de solucionar el problema de las múltiples intancias en sus proyectos de IP, P1 o P2.
El patrón de diseño Singleton (instancia única) está diseñado para restringir la creación de objetos pertenecientes a una clase o el valor de un tipo a un único objeto. Su intención consiste en garantizar que una clase sólo tenga una instancia y proporcionar un punto de acceso global a ella.
El patrón Singleton se implementa creando en nuestra clase un método que crea una instancia del objeto sólo si todavía no existe alguna. Para asegurar que la clase no puede ser instanciada nuevamente se regula el alcance del constructor (con atributos como protegido o privado).
La instrumentación del patrón puede ser delicada en programas con múltiples hilos de ejecución. Si dos hilos de ejecución intentan crear la instancia al mismo tiempo y esta no existe todavía, sólo uno de ellos debe lograr crear el objeto. La solución clásica para este problema es utilizar exclusión mutua en el método de creación de la clase que implementa el patrón.
Las situaciones más habituales de aplicación de este patrón son aquellas en las que dicha clase controla el acceso a un recurso físico único (como puede ser el ratón o un archivo abierto en modo exclusivo) o cuando cierto tipo de datos debe estar disponible para todos los demás objetos de la aplicación.
El patrón Singleton provee una única instancia global gracias a que:
- La propia clase es responsable de crear la única instancia.
- Permite el acceso global a dicha instancia mediante un método de clase.
- Declara el constructor de clase como privado para que no sea instanciable directamente.
Aquí tienen su implementación en Java:
[code lang=”java”]
public class Singleton {
private static Singleton INSTANCIA = null;
// Contructor privado
private Singleton() {
}
// Creador sincronizado para protegerse de posibles problemas
// multi-hilo, otra prueba para evitar instanciación múltiple
private synchronized static void crearInstancia() {
if (INSTANCIA == null) {
INSTANCIA = new Singleton();
}
}
public static Singleton getInstance() {
if (INSTANCIA == null) crearInstancia();
return INSTANCIA;
}
}
[/code]
Espero les sirva de algo.
Comentarios ( 6 )
Toy en 5to e igual me ha servido. Gracias.
En el blog This.Play() están publicados 3 libros que son oro puro, uno de ellos es el “Head First Design Patterns”, está muy bueno para estudiar patrones. Ojalá Joge se motive y vuelva a postear.
Sí para aprender patrones de diseños lo mejor que he visto es el Head First Design Pattern y el libro Patterns for Dummies, muy buenos los dos.
En cuanto a Jorge, el bloguer de this.play desde hace unos días es padre, lo vi ayer y lo felicité personalmente. Seguro nos sorprende con un post con fotos del niño. Seguro es informático igual que el padre 😉 .
Singleton… un arma de doble filo.>. En muchos casos es más simple pasar los objetos (singleton) como referencias a los objetos que los necesitan, en vez de acceder globalmente a él desde un método. El principal desafío con este patrón es que deja en las manos de los programadores mantener la visibilidad apropiada. Encontrar el balance correcto es crítico para la flexibilidad del software. El singleton ataca directamente el patrón Bajo Acoplamiento, ya que es capaz de acoplar cierto número considerable de clases en un software a él (ver consecuencias del acoplamiento en el software).
Una de las principales características que podemos encontrar en varios libros, artículos y páginas de internet sobre el patrón singlenton, también mencionada en este post es la siguiente: “… una clase sólo tenga una instancia y proporcionar un punto de acceso global a ella…”
Esta característica de “acceso global” tiende a confundir, muchas veces pensamos en el singleton incorrectamente como un remplazo para una variable global, el singleton es por propósito y objetivo una variable global. Pero esto no quiere decir que se use en el modo que se usaba, como antaño en la programación estructurada.
El patrón singleton es uno de los más usados incorrectamente, entonces nos hacemos la pregunta. ¿Cuándo estamos usando innecesariamente el Singleton? La respuesta en pocas palabras: <
Generalmente tenemos el hábito de usar “Datos Globales”, entonces depositamos estos en un singleton. Por consiguiente el singleton aparece cada vez que existan cuestiones relacionadas con esos datos globales. La respuesta al problema de los Datos globales No es “Hacer un Singleton”, la respuesta es “Por que estas usando datos globales”. Cambiar el nombre a las variables globales no cambia el problema, de hecho lo empeora, porque pensamos que no estamos haciendo “aquello”, estamos haciendo “esto”. Sin embargo esto y aquello es lo mismo.
Una sugerencia,… cuando usen un patrón de diseño se debe investigar con empeño sus desventajas y consecuencias tanto como sus ventajas, ya que puede hacernos pensar que estamos haciendo lo correcto, lo que “está probado”, sin danos cuenta los problemas que estamos introduciendo. Debido a esto existe una tendencia de hacer uso desmesurado de los patrones de diseño sin contemplar consecuencias.
Singleton… un arma de doble filo.
Una de las principales características que podemos encontrar en varios libros, artículos y páginas de internet sobre el patrón singlenton, también mencionada en este post es la siguiente: “… una clase sólo tenga una instancia y proporcionar un punto de acceso global a ella…”Esta característica de “acceso global” tiende a confundir, muchas veces pensamos en el singleton incorrectamente como un remplazo para una variable global, el singleton es por propósito y objetivo una variable global. Pero esto no quiere decir que se use en el modo que se usaba, como antaño en la programación estructurada.
El patrón singleton es uno de los más usados incorrectamente, entonces nos hacemos la pregunta. ¿Cuándo estamos usando innecesariamente el Singleton? La respuesta en pocas palabras: < <Casi siempre >>. En muchos casos es más simple pasar los objetos (singleton) como referencias a los objetos que los necesitan, en vez de acceder globalmente a él desde un método. El principal desafío con este patrón es que deja en las manos de los programadores mantener la visibilidad apropiada. Encontrar el balance correcto es crítico para la flexibilidad del software. El singleton ataca directamente el patrón Bajo Acoplamiento, ya que es capaz de acoplar cierto número considerable de clases en un software a él (ver consecuencias del acoplamiento en el software).
Generalmente tenemos el hábito de usar “Datos Globales”, entonces depositamos estos en un singleton. Por consiguiente el singleton aparece cada vez que existan cuestiones relacionadas con esos datos globales. La respuesta al problema de los Datos globales No es “Hacer un Singleton”, la respuesta es “Por que estas usando datos globales”. Cambiar el nombre a las variables globales no cambia el problema, de hecho lo empeora, porque pensamos que no estamos haciendo “aquello”, estamos haciendo “esto”. Sin embargo esto y aquello es lo mismo.
Una sugerencia,… cuando usen un patrón de diseño se debe investigar con empeño sus desventajas y consecuencias tanto como sus ventajas, ya que puede hacernos pensar que estamos haciendo lo correcto, lo que “está probado”, sin darnos cuenta los problemas que estamos introduciendo. Debido a esto existe una tendencia de hacer uso desmesurado de los patrones de diseño sin contemplar consecuencias.
No siempre el singleton es un arma de doble filo muchas veces es bueno utilizarlo por ejemplo: imaginen una aplicacion especializada en envio de Mensajes de cualkier tipo ya sean SMS como MMS y ke tiene una relacion del tipo: ModenHandler (clase que se encarga del manejo del Modem) tiene un PortHandler (Clase que se encarga del manejo de la configuracion de los puertos del Modem). El patron singleton se puede utilizar para garantizar la creacion de una instancia unica a la hora de instanciar el PortHandler ya que cuando la ModemHandler vaya a configurar los puertos de comunicacion solo instanciara un solo objeto PortHandler y luego accederia a el de forma Globlal a traves de una funcion que tiene implementada garantizando así mayor efectividad de la aplicacion en general. Como ves no es ke uno kiera hacer “esto” o “aquello” sino que se busca exactamente el patron de diseño que se ajusta al problema que uno quiere y creeme cuando quieres garantizar que solo se genere una sola instancia de una clase…. Singleton es el patron que debes utilizar.
El patrón tiene un buen uso y hasta ahora casi siempre es necesario su uso en las tareas extraclase de programación para evitar complicaciones, sin embargo, hay algo en lo que no se fijan la mayoría de los que utilizan este patrón.
Cuando se lee los libros de Meyer, se puede apreciar que algo que se debe cumplir cuando se construye un software orientado a objetos, es que cada clase que se diseñe e implemente siempre debe tener constructor y en muchos casos destructor, y que el uso de todas las clases que se hayan implementado debe ser homogéneo, es decir, la forma de crear instancias y de acceder a las operaciones (métodos) debe ser el mismo.
Claramente la solución del patrón Singleton más conocida no cumple con esto, lo importante en este caso es conocer que la solución para Java (y para otros como C++) es esa, porque el lenguaje no permite hacer otra implementación que solucione el problema que ataca el patrón Singleton, sin embargo, otros lenguajes, por ejemplo python, cuentan con un mecanismo que permite dar solución a este patrón, sin utilizar métodos estáticos ni ocultar al usuario de una clase el constructor.
En mi opinión, es muy importante el uso de los patrones, pero siempre debemos conocer por qué esa solución es así, hasta dónde cumple con los principios de diseño que “debemos” utilizar para que el software esté acorde al paradigma que estamos utilizando (generalmente Programación Orientada a Objetos)
Saludos.