En ocasiones necesitamos un objeto común a toda la aplicación. Un objeto del que solo queramos una instancia. Normalmente este tipo de objetos se relacionan con objetos con una función específica para toda la aplicación, como por ejemplo un pool de conexiones a una base de datos o las factorías concretas de un patrón Factory. Para proporcionar la funcionalidad del patrón Singleton debemos tener en cuenta tres cosas:

  • Proveer una manera de evitar más de una instancia de la clase.
  • Crear un punto de acceso único a la clase.
  • Tener cuidado con la concurrencia de la aplicación y sus diferentes hilos.

Para el primer y segundo punto debemos considerar dos cosas: la primera es que si queremos un objeto que comparta su estado en toda la aplicación, este objeto deberá tener ser por definición, estático, y la segunda es que si queremos una sola instancia de este, debemos proveer algún tipo de mecanismo para averiguar si existe una instancia creada de este objeto. Una forma de conseguir ambas cosas puede ser la siguiente:

Hemos creado un constructor privado y de esta forma hemos forzando la creación de un objeto estático en un método público que chequea si está inicializado. En caso de no estarlo, lo inicializa y en caso de ya estar inicializado lo devuelve, pero nunca lo crea dos veces.

Nunca lo crea dos veces… a no ser que se de la circunstancia de que dos o más hilos independientes llamen al mismo tiempo el método y chequeen paralelamente que no existe el objeto… en cuyo caso tendríamos dos instancias creadas y un gran problema.

¿Cómo lidiar con el problema del multithreading sobre un método? Java provee la palabra reservada synchronized para evitar que dos o mas hilos ejecuten simultáneamente el mismo bloque de código. Si eres de los que crees que la sincronización es un recurso caro de implementar en términos de rendimiento, no te preocupes, porque parece ser que está muy sobrevalorado ese coste1. Sin embargo, si te sigue preocupando mucho el tema del rendimiento, puedes delegar la inicialización de tu objeto en tiempo de carga de la clase (que es por definición thread-safe) de la siguiente forma:

No te olvides de que si tu objeto va a ser escrito y leído varias veces tendrás que completar tu implementación con

Si por ultimo eres un paranoico o paranoica de la posibilidad de dos instancias de tipo tu Singleton en la misma aplicación deberías anota tu clase como final y evitar la clonación de tu objeto sobrescribiendo el método clone() que todos los objetos heredan de Object.

Por curiosidad, el diagrama UML para una clase Singleton es el siguiente:

1-https://www.ibm.com/developerworks/java/library/j-jtp04223/index.html