3. Singleton
El patrón singleton provee un mecanismo para limitar el número de instancias de una clase a uno. Por lo tanto el mismo objeto es siempre compartido por distintas partes del código. Un Singleton puede ser visto como una solución más elegante para una variable global porque los datos son abstraídos por detrás de la interfaz de la clase singleton. Primero vemos cómo puede ser implementado un singleton en C++ y luego proveemos la solución con Python con las mismas características.
||
class Singleton {
public:
static Singleton& Handle();
private:
static Singleton* psingle;
Singleton();
Singleton( const Singleton& );
Singleton& operator=( const Singleton& );
};
Figura 1. Definición de una clase Singleton en C++ ||
Nuestra definición mínima de un singleton (Fig. 1) tiene solo un miembro público: el método manejador de la clase Handler. La interfaz definida no es muy útil comotal, porque el cliente no puede hacer nada con la instancia, pero ahoranos concentramos solo en las técnicas que aseguran una solainstancia del singleton a la vez.
El constructor privado prohibe la creación de un objeto fuera de laclase. Por ende los clientes de la clase tienen que dependeren la función miembro estática:ya sea que estacree una nueva instancia o devuelva una referencia al objeto singleton(Fig. 2 ).
||
Singleton& Singleton::Handle() {
if( !psingle ) {
psingle = new Singleton;
}
return *psingle;
}
Figura 2.Método Handle de la clase ||
Ya que Python no tiene constructores privados debemos encontrar una alternativa para prevenir instanciaciones. Nuestra aproximación en la figura 3 es para lanzar una excepción si el objeto singleton ya se encuentra instanciado (el atributo privado de la clase single es distinto de None). ¡El objeto excepción es la instancia singleton! La desventaja de esta solución es que requiere que los clientes estén preparados para la excepción. También podría ser argumentado que utilizar excepciones para otros propósitos distintos del manejo de errores no es un muy buen estilo. Estas consideraciones pueden ser eliminadas hasta cierto punto proveyendo un manejador similar al de la figura 2. Esta función oculta los detalles de la instanciación poco ortodoxa y devuelve una referencia al objeto singleton (Fig. 4).
||
class Singleton:
single = None
def init( self ):
if
Singleton.single:
raise
Singleton.single
Singleton.single
= self
Figura 3. Clase Singleton en Python ||
Debido al sistema de tipos de Python el código en la figura 4 funciona para toda la jerarquía singleton. Consideremos la siguiente situación: la clase Singleton tiene sublcases Child y Junior como se muestra en la figura 5. Debido a que existe una relación es-un entre la clase base y la subclase solamente puede haber una instancia de toda la jerarquía. Una instancia de Singleton o Junior puede ser creada con la función Handle. El constructor de la clase toma un parámetro -explícito- para que la instanciación deba ser hecha con una llamada directa al constructor o a una función especializada de manejo. El siguiente código demuestra la jerarquía Singleton:
>>> child = Child( 'Monty' )
>>> junior = Handle( Junior )
>>> junior.name()
'Monty'
>>> single = Handle()
>>> single
<Child instance at d1d88>
Algunas veces es conveniente decidir en tiempo de ejecución cuál clase singleton será instanciada. El GOF propone un acercamiento basado en registro, donde el cliente consulta a un objeto especial registro, el cual contiene un alista de pares nombre-Singleton. Solicitando un singleton por su nombre, elcliente recibe una referencia a la instancia correspondiente deSingleton. Actualizar el registro puede serproblemático: ¿Quién registra unSingleton? si es la instancia misma de Singleton (en suconstructor) !entonces todos los posibles Singleton deben serinstanciados para poder ser accesibles por los clientes del registro!
Afortunadamente la simplificación es posible a través de los conceptos de domino de nombres de Python. Los ámbitos local y global - o en su defecto su representación de diccionario - pueden ser accedidos por funciones locales y globales. Por ejemplo podríamosinstanciar Junior:
>>> name = 'Junior'
>>> sclass = globals()[name]
>>> junior = Handle( sclass )
>>> junior
<Junior instance at d1bd8>
Por supuesto, ahora el registro (en el ámbito del diccionario) contiene mucho más que solo información relacionada al singleton, por lo que siempre existe un riesgo de que un cliente trate alguna función como una clase Singleton. Esta desafortunada coincidencia puede ser evitada hasta cierto puntoutilizando alguna convención de nomenclatura para lossingleton. Un objeto de registro específico es unabuena idea aún en el ambiente Python. Los clientesno deberían acceder a los diccionarios de ámbitodirectamente sion a través del registro. Ahora elregistro puede detectar y denegar cualquier búsqueda desingleton que sean ilegales de acuerdo con la convención denomenclatura. Nuevamente, esta aproximacióndepende en la cortesía de los clientes.
Tal vez la solución más segura y directa es la de registro en el nivel del módulo. Cada módulo que contenga clases Singleton deberían también contener sentencias de inicialización que registren los nombres de las clases con el módulo de registro. Debido a que los módulos son inicializados sólo la primera vez que son importados, un cliente obtiene acceso al registro importando el módulo del registro. En cierto modo un módulo puede ser visto como un Sigleton rudimentario. Una ventaja de este estilo de registro explícito es la opción de implementar tantos registros sofisticados como sean necesarios. En otras palabras podremos almacenar más información acerca de los singleton que solo los nombres de las clases, por ejemplo los nombres de los módulos, diferentes restricciones y así. El registro puede también ofrecer diferentes servicios para las búsquedas de singleton, estadísticas y depuración, por ejemplo.
||
def Handle( x = Singleton ):
try:
single
= x()
except Singleton, s:
single
= s
return
single
Figura 4. Función Handle function ||
||
class Child( Singleton ):
def init( self, name ):
Singleton.init(
self )
self.name
= name
def name( self ):
return
self.name
class Junior( Singleton ):
pass
Figure 5. Singleton subclasses ||
Autor y licencia de 'Patrones de diseño en Python - Singleton'
Mononeurona Extraído de: http://www.mononeurona.org/index.php?idp=460
Esta obra está bajo una licencia de Creative Commons.
|
|
Este trabajo está licenciado bajo la Creative Commons License. 1999-2005 © :: MonoNeurona.org :: |
|
|
|
Este contenido ha sido recopilado por el equipo de Wikilearning. Todo el contenido recopilado se ha obtenido respetando y comunicando en nuestro site la licencia de cada fuente.
|
|
Wikilearning tiene permiso expreso por escrito de los autores para publicar los contenidos que ha extraído de otras webs, incluyendo su uso comercial.
|
|
Wikis relacionados con 'Patrones de diseño en Python - Singleton'
Esto es un curso intensivo de introducción mínima al lenguaje de programación Python. Si te...
Más »
Uno de los patrones de diseño sin lugar a dudas más utilizado y conocido, es...
Más »
La programación de aplicaciones para la Web es una técnica que ya lleva suficientes años...
Más »
La programación de aplicaciones para la Web es una técnica que ya lleva suficientes años...
Más »
PHP se ha convertido en el lenguaje de facto de Internet y no es difícil...
Más »
¿Estás seguro de que deseas eliminar este capítulo?