Patrones de diseño en Python - Cadena de responsabilidad
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 {
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: 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 ): 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 )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:
>>> 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
... print 'Name: ' + e.name
...
>>> sd.Handle_odd = PrintName
>>> msg.Handle( eodd )
Name: odd
>>> del sd.Handle_odd
>>> msg.Handle( eodd )
Default: odd
|
Opiniona sobre 'Patrones de diseño en Python - Cadena de responsabilidad' (1)
Opina sobre este tutorial |

