Inicio / Wikis / Tutoriales / Patrones de diseño en Python - Cadena de responsabilidad

Patrones de diseño en Python - Cadena de responsabilidad

(1 opiniones)
Tutorial creado por
27 de Octubre de 2005
Programación estructuradaServidores de contenidos
La motivación detrás de un patrón de cadena de responsabilidad es crear un sistema que pueda servir a diversas solicitudes de manera jerárquica.  En otras palabras, si un objeto que es parte de un sistema no sabe cómo responder a una solicitud en específico, la pasa a lo largo del árbol de objetos.  Como el nombre lo implica, cada objeto a lo largo de la ruta de la solicitud puede tomar la responsabilidad y atender la solicitud.

Un patrón de cadena de responsabilidad es a menudo utilizado en el contexto de interfaces gráficas de usuario donde un objeto puede contener varios otros objetos.  Como el ambiente de ventanas genera eventos los objetos o los manejan o los pasan a su objeto padre(contenedor), como en la figura 6.




Figura 6. Una jerarquía simple de ventanas


Si MsgText recibe unevento su método Handle o maneja el evento o llama almétodo Handle de SendDialog, y así sucesivamente.   MsgText no necesita saber qué objeto - si lo hay - manejará el evento; la jerarquía no tiene que ser preparada.  En otrocontexto un objeto MsgText podría comportarse similarmente y así las jerarquías pueden ser modificadas en tiempo de ejecución.  La jerarquía no requiere necesariamente ser en forma de árbol.  Una variación del patrón podría ser un sistema en el que los objetos crearan una estructura estilo anillo y algunos o todos los objetos pudieran actuar como clientes así como parte de la cadena.

La implementación del patrón en C++ es relativamente directa: en nuestro ejemplo de GUI cada objeto podría ser una subclase de la clase Widget definida en la figura 7. Mientras que esto es también una solución alcanzable en Python, no utiliza el modelo de objetos de Python a su potencial máximo.  Una aproximación más dinámica y flexible es utilizar las técnicas introducidas en el patrón de despacho de comandos de Guido van Rossum [vR97]: búsqueda y adición dinámica de atributos.




class Widget {

public:
Widget( Widget* pw ): pwParent( pw ) {}
virtual void Handle( Event );
private:
Widget* pwParent;
};

Figura 7.Definición de la clase Widget

Con Python no necesitamos restringirnos al conjunto predefinido de métodos como lo hicimos con la jerarquía Widget: el único camino para manejar este evento era llamando a Handle.  La idea detrás del patrón de despacho de comando es checar en tiempo de ejecución si el objeto tiene un método propio o no.  Nuestra clase Widget en Python(Fig. 8) provee a sus subclases con este mecanismo de despacho.  El uso de clases evento separadas (Event en la figura 8) enfatiza el hecho de que varias clases de información pueden ser transmitidas a través dela cadena.  Solamente el atributo name es asumido. Dado que nuevos atributos pueden ser añadidos dinámicamente y nuevos métodos pueden ser agregados a traves de sublcases, la interface de la clase base Event puede ser mantenida al mínimo.




class Event:
def __init__( self, name ):
self.name = name

class Widget:
def __init__( self, parent = None ):
self.__parent = parent
def Handle( self, event ):
handler = 'Handle_' + event.name
if hasattr( self, handler ):
method = getattr( self, handler )
method( event )
elif self.__parent:
self.__parent.Handle( event )
elif hasattr( self, 'HandleDefault' ):
self.HandleDefault( event )

Figura 8. Las clasesEvent y Widget en Python

Cuando un objeto evento es pasado al método Handle, una de cuatro cosas pueden pasar:

1.
Cada evento tiene su nombre asociado. Si Widget tiene un método correspondiente (llamado Handle_nombreevento), es ejecutado.
2.
Si el objeto no es el último de lacadena, pasa el objetoevento a su padre.
3.
Si el objeto tiene un manejador por defecto para toda clase de eventos(método HandleDefault) es invocado si el objeto es el último manejador posible.  Ya que HandleDefault debe siempre estar disponible sólo al final de la cadena, no es necesario ni recomendable tenerlo en la interface de la clase base.
4.
El objeto ignora el evento si no lo puede manejaro reenviar.



class MainWindow( Widget ):
def Handle_close( self, event ):
print 'MainWindow: ' + event.name
def HandleDefault( self, event ):
print 'Default: ' + event.name

class SendDialog( Widget ):
def Handle_paint( self, event ):
print 'SendDialog: ' + event.name

class MsgText( Widget ):
def Handle_down( self, event ):
print 'MsgText: ' + event.name

Figura 9. La jerarquía de clases de Widget en Python

Algunas clases Python para nuestro GUI de ejemplo son implementadas en la Figura 9.  El siguiente código construye la cadena y demuestra su uso:

>>> sd = SendDialog( mw )
>>> msg = MsgText( sd )
>>> edown = Event( 'down' )
>>> msg.Handle( edown )
MsgText: down
>>> epaint = Event( 'paint' )
>>> msg.Handle( epaint )
SendDialog: paint
>>> eodd = Event( 'odd' )
>>> msg.Handle( eodd )
Default: odd
Un aspecto curioso de nuestra solución es que un manejador de eventos no necesariamente requiere ser un método; puede también ser un objeto función.  Esto permite al programador añadir nuevos manejadores de eventos a objetos existentes en lugar de crear nuevas clases a través de la herencia.  Dadas las funciones de ámbito de Python, una función evento no puede acceder a los atributos del objeto contenedor.  Sin embargo, ya que la función evento por sí misma es un atributo puede ser borrada.  En otras palabras, las funciones evento proveen medios para crear temporalmente manejadores de eventos a una jerarquía de cadena de responsabilidad existente.  Un ejemplo simple:
... print 'Name: ' + e.name
...
>>> sd.Handle_odd = PrintName
>>> msg.Handle( eodd )
Name: odd
>>> del sd.Handle_odd
>>> msg.Handle( eodd )
Default: odd
Valora este capítulo: (1 opiniones)
Autor y licencia de 'Patrones de diseño en Python - Cadena de responsabilidad'
Mononeurona Extraído de: http://www.mononeurona.org/index.php?idp=460

Creative Commons License
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.

Opiniona sobre 'Patrones de diseño en Python - Cadena de responsabilidad' (1)

Tu nombre debe tener tres caracteres como mínimo.
Es necesario que te des de alta con una cuenta de correo válida.
Es necesario que te des de alta con una cuenta de correo válida.
El contenido del título de tu opinión debe tener tres caracteres como mínimo.
Es obligatorio que selecciones una valoración del recurso.
El contenido del comentario de tu opinión debe tener tres caracteres como mínimo.

Opina sobre este tutorial



* Valoración:
* Nombre:
* Correo electrónico:
* Título:
* Comentario:

Wikis relacionados con 'Patrones de diseño en Python - Cadena de responsabilidad'

Este artículo no pretende establecer métodos para la administración de la cadena de abastecimiento ni... Más »
La responsabilidad ambiental se asume a través de un concepto cultural, es una toma de... Más »
Esto es un curso intensivo de introducción mínima al lenguaje de programación Python. Si te... Más »
Actualmente una buena parte de las empresas chilenas están, fruto de los alcances del proceso... Más »
La naturaleza que rodea a cada hombre y en medio de la cual desarrolla su... Más »
¿Estás seguro de que deseas eliminar este capítulo?