Implementación del patrón Singleton en Scala
Saludos a todo el mundo (o todo el mundo que lea este blog). Como estoy un poco liado con otras entradas referentes a la charla de integración continua en Agile-Canarias, hoy hablaré de un tema sencillo que me ha surgido esta semana. Como implementar el patrón Singleton en Scala.
Para empezar y para todos aquellos que no sepan lo que es el patrón Singleton, se puede resumir en que es un patrón de diseño que permite mantener una única instancia de un determinado objeto. Esto es muy útil cuando se trata de un objeto cuya instanciación es muy costosa o simplemente porque modela un elemento que es único en la realidad.
A partir del diagrama de clase anterior nos podemos hacer una idea de su implementación en un lenguaje como por ejemplo Java, pero para que quede más claro, aquí va el código de un Singleton en Java :-) Esta sacado de la Wikipedia y es tan solo un ejemplo ilustrativo así que no le intentéis buscar un sentido más allá de ser un simple ejemplo (aunque como ejemplo funciona bien).
Ahora bien, si en Scala no disponemos del modificador static, cómo vamos a hacer esto?!?!?!?! Pues es muy sencillo, igual que hacemos para simular los métodos estáticos, con la declaración object en vez de class, es decir.
Como imagino que ya os habréis fijado, esta clase Java que yo he llamado Singleton, en la vida real tendrá más líneas de código referentes a su utilidad en el sistema que estemos implementando, pero para nosotros estarán contenidas en los puntos suspensivos (...) En Scala no es posible hacer un new Singleton, porque se trata de un object, pero podemos tener una factoría para crear una instancia del objeto deseado "de la clase Singleton", mientras que SingletonContainer sirve para mantener la referencia única.
Además como a todos nos gustar escribir poco, voy a dar una aproximación aún más corta a la implementación con Scala.
Más corto imposible :-) Pero seguro que muchos esto les suena raro porque el patrón Singleton suele ser autocontenido, es decir que no hay contenedor que instancia a otra clase mediante una factoría. Pues claro!!! Bien, por defecto en Scala un object es un Singleton en sí mismo, así que realmente no teníamos que hacer nada de nada, ¿por qué he hecho yo esto? Porque en algunos casos es simplemente necesario tener una instancia única que en realidad es de otra clase distinta, y este es el método más sencillo que he encontrado, de forma que mi código real es algo como lo siguiente.
De esta forma ahora tengo una instancia de Model (que es una clase de Jena, lo cual no viene a cuento ahora :-) que funciona como un Singleton en tan solo unas pocas líneas. Pero si BaseSemanticModel fuese la clase de la que quiero el Singleton, no tengo que hacer nada más que la implementación de la misma, porque luego la referencia a BaseSemanticModel es única y funciona como un Singleton en Scala.
Espero que me hayáis entendido, porque creo que ni yo mismo lo hago y que le sirva de algo a alguien.
Para empezar y para todos aquellos que no sepan lo que es el patrón Singleton, se puede resumir en que es un patrón de diseño que permite mantener una única instancia de un determinado objeto. Esto es muy útil cuando se trata de un objeto cuya instanciación es muy costosa o simplemente porque modela un elemento que es único en la realidad.
A partir del diagrama de clase anterior nos podemos hacer una idea de su implementación en un lenguaje como por ejemplo Java, pero para que quede más claro, aquí va el código de un Singleton en Java :-) Esta sacado de la Wikipedia y es tan solo un ejemplo ilustrativo así que no le intentéis buscar un sentido más allá de ser un simple ejemplo (aunque como ejemplo funciona bien).
public class Singleton {
private static final Singleton instance = new Singleton();
...
// El constructor privado impide la instanciación
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
...
}
Ahora bien, si en Scala no disponemos del modificador static, cómo vamos a hacer esto?!?!?!?! Pues es muy sencillo, igual que hacemos para simular los métodos estáticos, con la declaración object en vez de class, es decir.
object SingletonContainer {
val singleton = ... ; // instanciación desde una Factoría
def getInstance: Singleton = {
return singleton;
}
}
Como imagino que ya os habréis fijado, esta clase Java que yo he llamado Singleton, en la vida real tendrá más líneas de código referentes a su utilidad en el sistema que estemos implementando, pero para nosotros estarán contenidas en los puntos suspensivos (...) En Scala no es posible hacer un new Singleton, porque se trata de un object, pero podemos tener una factoría para crear una instancia del objeto deseado "de la clase Singleton", mientras que SingletonContainer sirve para mantener la referencia única.
Además como a todos nos gustar escribir poco, voy a dar una aproximación aún más corta a la implementación con Scala.
object SingletonContainer {
val getInstance = ... ; // instanciación desde una Factoría
}
Más corto imposible :-) Pero seguro que muchos esto les suena raro porque el patrón Singleton suele ser autocontenido, es decir que no hay contenedor que instancia a otra clase mediante una factoría. Pues claro!!! Bien, por defecto en Scala un object es un Singleton en sí mismo, así que realmente no teníamos que hacer nada de nada, ¿por qué he hecho yo esto? Porque en algunos casos es simplemente necesario tener una instancia única que en realidad es de otra clase distinta, y este es el método más sencillo que he encontrado, de forma que mi código real es algo como lo siguiente.
object BaseSemanticModel {
val getInstance = SemanticUtils.loadModelFromResourceFile(...);
}
De esta forma ahora tengo una instancia de Model (que es una clase de Jena, lo cual no viene a cuento ahora :-) que funciona como un Singleton en tan solo unas pocas líneas. Pero si BaseSemanticModel fuese la clase de la que quiero el Singleton, no tengo que hacer nada más que la implementación de la misma, porque luego la referencia a BaseSemanticModel es única y funciona como un Singleton en Scala.
Espero que me hayáis entendido, porque creo que ni yo mismo lo hago y que le sirva de algo a alguien.
Comentarios
Muchas gracias por tu apoyo incondicional :-)
Muchas gracias por tu apoyo incondicional :-)