Patrón Singleton en Python, con ejemplos
- El proyecto de este post lo puedes descargar pulsando AQUI.
- Este tutorial es una adaptación del tutorial Patrón Singleton en Java, con ejemplos.
El patrón singleton es un patrón de creación (Creational Design Pattern) que tiene como objetivo garantizar que una clase sólo tenga una instancia y proporcionar un único punto de acceso a esa instancia. Este patrón suele ser utilizado en temas de logging (entre otros) donde solo queremos tener una una instancia del logger que centralice todo.
Existen muchas formas de implementar este patrón; vamos a comentar dos, una sencilla y otra que es interesante comentar por su parecido a Java, las cuales podemos consultar en: http://python-3-patterns-idioms-test.readthedocs.io/en/latest/Singleton.html.
Tal y como se haría en Java
Podemos hacer una implementación similar a la que haríamos en Java, donde lo que estamos haciendo es declarar una clase interna privada (notada por __ ) ya que en python no podemos hacer constructores privados. En esta clase privada tenemos el método de inicialización (__init__), y el método que nos convierte el objeto a string (__str__) para que veamos que está siempre en la misma posición de memoria.
La primera vez que usamos el constructor (__new__) creamos la instancia ya que se cumple la condicion de que no tenemos instancia, y, el resto de veces no, simulando los constructores privados en java. También podemos ver que los getters y los setters son accedidos a través de __getattr__ y __setattr__ que llaman a los de la instancia.
# coding=utf-8 class SoyUnico(object): class __SoyUnico: def __init__(self): self.nombre = None def __str__(self): return `self` + ' ' + self.nombre instance = None def __new__(cls): if not SoyUnico.instance: SoyUnico.instance = SoyUnico.__SoyUnico() return SoyUnico.instance def __getattr__(self, nombre): return getattr(self.instance, nombre) def __setattr__(self, nombre, valor): return setattr(self.instance, nombre, valor) ricardo = SoyUnico() ricardo.nombre = "Ricardo Moya" print(ricardo) ramon = SoyUnico() ramon.nombre = "Ramón Invarato" print(ramon) print(ricardo) print(ramon)
Si lo ejecutamos:
<__main__.__SoyUnico instance at 0x7f9f88b24878> Ricardo Moya <__main__.__SoyUnico instance at 0x7f9f88b24878> Ramón Invarato <__main__.__SoyUnico instance at 0x7f9f88b24878> Ramón Invarato <__main__.__SoyUnico instance at 0x7f9f88b24878> Ramón Invarato
Después de ejecutar el código vemos que lo que tenemos es siempre la variable en la misma posición de memoria (única instancia) y que sólo contiene el último valor porque solo hay una variable.
Forma sencilla
Podemos usar una forma simplificada, donde lo que hacemos la primera vez (usando el constructor nuevamente (__new__)) es instanciar la clase ya que la variable __instance es none y el resto de veces al tener valor, la devolvemos directamente.
# coding=utf-8 class SoyUnico(object): __instance = None nombre = None def __str__(self): return `self` + ' ' + self.nombre def __new__(cls): if SoyUnico.__instance is None: SoyUnico.__instance = object.__new__(cls) return SoyUnico.__instance ricardo = SoyUnico() ricardo.nombre = "Ricardo Moya" print(ricardo) ramon = SoyUnico() ramon.nombre = "Ramón Invarato" print(ramon) print(ricardo) print(ramon)
Ejecutando el código obtenemos:
<__main__.SoyUnico object at 0x7f53d6226050> Ricardo Moya <__main__.SoyUnico object at 0x7f53d6226050> Ramón Invarato <__main__.SoyUnico object at 0x7f53d6226050> Ramón Invarato <__main__.SoyUnico object at 0x7f53d6226050> Ramón Invarato
En el artículo pones «Cómo se haría en Java» creó que debería decir: «Cómo se haría en Python»
Esta haciendo alusión a la forma en que se haría en java, ya se sobre entiende que lo va ha hacer en python.
Hola, el «como» está escrito sin tilde, por lo tanto no denota una qüestión, sino una afirmación o comparación. (No estoy serguro de si cuando leerías estaba con la tilde jeje). Saludos.
Era una comparativa sustituible por «Se programa en Python como se haría en Java».
Como genera confusión cambio «Como se haría en Java» a «Tal y como se haría en Java».