Patrón: Singleton
Diagrama UML
El patrón Singleton indica que, en el desarrollo del software, las diferentes clases o entidades determinadas, sólo pueden tener un único objeto. Esto quiere decir que una clase o entidad, sólo se puede instanciar una vez, siendo un objeto único el resultado de su instancia.Este patrón es muy útil cuando se debe crear un clase común y global para el sistema, donde no importe crear varias instancias de la misma, por ejemplo se podría pensar en una clase conexión que se utilice por toda la aplicación, si creamos varios objetos de esta clase se podría llenar el heap del sistema con objetos innecesarios que se crean cada vez que se crea una nueva instanciamos la clase, por eso si se restringe la creación a un solo objeto se podría evitar problemas con el rendimiento y se ahorra un gran trabajo para el garbage collector.Otro ejemplo que puede ser útil para la comprensión del mismo es a la hora de crear un objeto que carga algunos parámetros de un archivo, de esta manera se evita que el sistema lea este archivo cada vez que sea necesario, en vez de eso tan solo se lee una vez cuando se llama al objeto que contiene los parámetros necesarios. Los principios Solid en desarrollo de software, velan por la buena estructura del código generado, además de evitar que el mismo esté “sucio”. El objetivo de seguir los principios SOLID es lograr que el código tenga la mejor y más clara estructura posible, de manera que se logre una mejor comprensión del mismo y un mantenimiento lo más sencillo posible.
En principio el patrón no cumple con ningún principio SOLID, tal como se muestra en la imagen
Para ejemplificar este patrón se
utilizará este código de Singleton:
Principio de Single Responsability
El principio de responsabilidad simple consiste en que una clase debe tener una sola función dentro del sistema y la implementación debería cambiar únicamente cuando hay un cambio crítico en el sistema.
El Patrón de diseño Singleton de forma predeterminada no cumple este principio, ya que este patrón requiere de una alta cohesión entre las clases del sistema, y por esta razón un simple cambio en el sistema requiere un cambio mayor en las clases de este.
Lo que se debe hacer para que este patrón cumpla con el principio de responsabilidad simple es pasar el objeto del Singleton por medio de parámetros, de esta forma reduce el acoplamiento entre las clases del sistema.
Para hacer que el Singleton cumpla con este patrón se debe llamar a la instancia ya creada por medio de un parámetro.
Principio de Segregación de Interfaz
El principio de
segregación de interfaz define que no obliguemos a los clientes a
depender de clases o interfaces que no necesitan usar. Esto podría darse cuando
una clase o interfaz tiene más métodos de los que un cliente necesita utilizar.
Es muy posible que sirva a varios objetos cliente con diferentes
responsabilidades, con lo que cada una de las diferentes responsabilidades
debería estar dividida en varias entidades.
El principio nos dice
que los clientes no deben estar forzados u obligados a depender de métodos que
no va a utilizar.
El patrón singleton cumple con este objetivo si se le hacen los cambios propuestos en el diagrama anterior ya que al tener una única instancia de un objeto no se presta a que se den “casos” como el anterior de tener varios clientes y que cada uno utilice un método diferente, con esto las interfaces están definidas básicamente para un único objeto, los métodos creados van a ser únicamente para el mismo y con ello los clientes no se verán forzados a depender de métodos que no se utilizan.
NOTA: Arreglando Este Principio se asegura que se cumpla el siguiente
Dependency Inversion Principle
El principio Dependency Inversion indica que módulos de alto nivel no deben de depender de módulos de bajo nivel. Esto se logra por medio de la creación de clases abstractas en medio de los módulos o clases de alto nivel y módulos detallados de bajo nivel.
¿Se cumple el principio Dependency Inversion en el patrón Singleton?
Se cumple, pero dependiendo de la manera en que se utilicen las clases abstractas. Una manera de hacer que se utilicen clases abstractas (aplicando Dependency Inversion) es usar el Abstract Factory, el cual es una interfaz o clase abstracta que genera familias de objetos relacionados o dependientes. El principal participante de Abstract Factory es la clase abstracta llamada FabricaAbstracta, la cual si cumple el patrón Singleton porque una aplicación de la misma solo necesita de una instancia, por lo tanto cumple que sea instanciada una sola vez y que su tipo de objeto resultante sea único.
En el siguiente ejemplo se puede ver que la clase abstracta programa como Singleton es FabricaDiscos. Posee dos métodos.
public interface FabricaDiscos {
public BluRay crearBluRay();
public DVD crearDVD();
En lo siguiente se muestra una aplicación de la
FabricaAbstracta llamada FabricaDiscos. En este caso la aplicación se
denomina FabricaDiscos_CapaSimple.
public class
FabricaDiscos_CapaSimple implements FabricaDiscos
{
@Override
public BluRay crearBluRay() {
return new BluRay_CapaSimple(); }
@Override
public DVD crearDVD() {
return new DVD_CapaSimple();
}
En lo siguiente se
muestra la manera en que son utilizadas la FabricaAbstracta y su aplicación, de
manera que se puedan utilizar los métodos de la aplicación antes creada.
FabricaDiscos
fabrica;
DVD dvd;
BluRay bluray;
fabrica = new FabricaDiscos_CapaSimple();
dvd = fabrica.crearDVD();
bluray = fabrica.crearBluRay();
System.out.println(dvd);
System.out.println(bluray);
En resumen, el principio Dependency Inversion se cumple en el patrón Singleton dependiendo del método que se utilice para representar las clases abstractas. En este caso, usando AbstractFactory el principio se cumple en el patrón porque las clases abstractas creadas solo se instancian una vez. Una aplicación de cada una de ellas solo necesita una instancia, por lo tanto, si se cumple. Todo depende de la manera de programar las clases abstractas, porque para que sea Singleton tiene que instanciarse solo y una vez y para que haya Dependency Inversion tiene que ser por medio de clases abstractas, entonces esas clases abstractas solo pueden ser instanciadas una vez.
Principio de Sustitución de Liscov
Este principio dice
que cada clase
que hereda de otra puede usarse como su padre sin necesidad de conocer las diferencias
entre ellas.
El patrón de
Programación Orientada a Objetos, Singleton, no cumple con este principio, pues
como podemos ver en el ejemplo del código, el constructor de la clase Singleton
es privado, por lo tanto, no se puede hacer herencia, aunque en realidad no es
un constructor en sí, pues por la naturaleza del patrón hay que evitar la
instanciación de varios objetos.
En caso de querer
corregir el patrón para que se cumpla el principio, se podrían hacer los
cambios que podemos ver en el ejemplo del siguiente código, en donde se
modifica el constructor de la clase padre por protected, para que sus hijos
puedan tener acceso a la clase padre.
Pero en este caso solo cumpliría con el Principio de Liscov y no con los de más, para ello se podría hacer como en le siguiente imagen, en donde las clases Singleton heredan de una Interface.
Principio de Open Closed
En este caso, el
principio Open Closed indica que las clases o entidades generadas deben de
poder entenderse (esto significa adquirir más atributos, funciones, etc), pero
no modificarse. No modificarse significa no cambiar o alterar las
funcionalidades ya utilizadas, al igual que con variables y atributos. Para
cumplir con el principio, se deben de seguir consejos como:
·
Todas las variables de clase
deben de ser privadas
·
No usar variables globales
·
Evitar setters
¿Se cumple el principio Open
Closed en el patrón Singleton?
Sí, se cumple si se le
aplican las correcciones correspondientes al diagrama anterior. Esto se da
porque en el Singleton, para que ningún otro programa o función sea capaz de
generar objetos del tipo de clase antes definido, se necesita crear
constructores privados, que usan variables privadas antes definidas para poder
almacenar referencias al objeto que se crea a través del constructor. Por lo tanto,
las variables del Singleton deben de ser privadas, sentencia que dicta el
principio Open Closed. En Singleton no se usan variables globales, ya que todas
se definen de manera interna y todas privadas. En Singleton se pueden usar
setters de tipo público, pero el Open Closed no dicta que no se debe de usar
setters del todo, solo evitarlos.
Utilizaremos como ejemplo un código en lenguaje Java, para mostrar el patrón Singleton con los cambios necesarios para que cumpla con los principios SOLID.
Material consultado:
- Recurso en línea Ble,C . Principios S.O.L.I.D 2010
- Recurso en línea Lay , D. SOLID: Principio de segregación de Interfaces - Palabras sobre código 2015-05-01
- Principio de sustitución de Liskov - Wikipedia, la enciclopedia libre (s. f.). Recuperado de https://es.wikipedia.org/wiki/Principio_de_sustituci%C3%B3n_de_Liskov
- Java - Is it possible to apply inheritance to a Singleton class? - Stack Overflow (s. f.). Recuperado de http://stackoverflow.com/questions/2772977/is-it-possible-to-apply-inheritance-to-a-singleton-class
- Principio de sustitución de Liskov - Wikipedia, la enciclopedia libre (s. f.). Recuperado de https://es.wikipedia.org/wiki/Principio_de_sustituci%C3%B3n_de_Liskov
- Csaba, P. (2014, 24 de Enero). SOLID: Part 3 - Liskov Substitution & Interface Segregation Principles Recuperado de http://code.tutsplus.com/tutorials/solid-part-3-liskov-substitution-interface-segregation-principles--net-36710
- Singleton - Wikipedia, la enciclopedia libre (s. f.). Recuperado de https://es.wikipedia.org/wiki/Singleton
- Recurso en línea Henao , C. CoDejaVu: Ejemplo Patrón Singleton 2013-07-14
- Ejemplo de Java Singleton (Patrones y ClassLoaders) - Arquitectura Java (s. f.). Recuperado el 15 de Abril del 2016, de http://www.arquitecturajava.com/ejemplo-de-java-singleton-patrones-classloaders/
- Factoría Abstracta | Marco de Desarrollo de la Junta de Andalucía (s. f.). Recuperado el 15 de Abril del 2016, de http://www.juntadeandalucia.es/servicios/madeja/contenido/recurso/191
- Patrón Abstract Factory - Línea de Código (s. f.). Recuperado el 15 de Abril del 2016, de http://lineadecodigo.com/patrones/patron-abstract-factory/
- Ejemplos de Singleton | Jarroba (s. f.). Recuperado el 15 de Abril del 2016, de http://jarroba.com/patron-singleton-en-java-con-ejemplos/