Event-Driven programming Mediator pattern Ricardo Poblete Jara Flex, Actionscript3 Ricardo Poblete Jara 15/04/2008 – 16/04/2008
Agenda
Objetivos
Razones
Objeto “Event”. A bucear.
Formas de eventos
Práctica
Patrón de diseño (Mediator)
Razones
Razones
¿Por qué?
Han ocurrido problemas al vincular directamente un objeto
Sobre todo cuando aún no está instanciado
Necesitamos hacer componentes con bajo acoplamiento
Es necesario conocer cuando un componente que me interesa hizo algo
No necesito invocar directamente al componente
¿Quiénes participan?
Componentes y clase event
Objetivos
Objetivos
General
Conceptualizar y comprender eventos en AS3 para fabricar componentes de bajo acoplamiento.
Específico
Capacidad de conceptualizar componentes independientes
Fabricar eventos personalizables
Coordinar y comunicar instancias de componentes
Objeto “Event” A bucear
Objeto “Event”. El piquero
En AS3 cada evento se representa mediante un objeto de evento, que es una instancia de la clase Event o de alguna de sus subclases
Por ser una clase podemos extenderla.
Creacion de un evento
Evento:Event = new Event();
Eventos
En lenguajes OO, si un objeto necesita notificar a un objeto B que algo importante ha sucedido, esto se realiza usando un patrón de diseño llamado “Observador”
El patrón Observador define una dependencia del tipo uno-a-muchos entre objetos, de manera que cuando uno de los objetos cambia su estado, el observador se encarga de notificar este cambio a todos los otros dependientes.
El objetivo de este patrón es desacoplar la clase de los objetos clientes del objeto, aumentando la modularidad del lenguaje, así como evitar bucles de actualización
Este patrón suele observarse en los marcos de interfaces gráficas orientados a objetos, en los que la forma de capturar los eventos es suscribir 'listeners' a los objetos que pueden disparar eventos.
Observer (patrón de diseño). http://es.wikipedia.org/wiki/Observer_(patr%C3%B3n_de_dise%C3%B1o)
Eventos (II) Patrón Observador
Eventos (III)
AS3 implementa este patron de diseño usando el modelo de eventos. Los objetos lanzan eventos a otros objetos.
Los eventos de sistema son lanzados por el AVM (ActionScript Virtual Machine), mientras los otros son lanzados como resultado de las interacciones de usuario con la aplicación, como el click en un boton o el movimiento del mouse
Por ejemplo
Cuando el flash player termina de crear un objeto, lanza el evento creationComplete.
Clases pueden lanzar eventos de acuerdo a la logica del negocio en la aplicación
Objetos de la aplicación pueden enviar eventos personalizados a otro objeto.
Eventos (IV)
En una aplicación MXMl, solo debemos especificar el nombre del evento y la función que se ejecutara al ocurrir el evento (handler function) como atributo del componente, sin preocuparse como se hace en código AS3.
<mx: button click=“agregar()” />
Pero todos los eventos en Flex son subclases de la clase flash. events.Event, y en un codigo As3 podemos registrar “listener” que escuchen o detecten los eventos ademas de especificar la funcion handler.
Cuando el “event listener” detecta el evento, llama a la función (handler function), esta recibe un objeto evento como parámetro, el cual contiene los atributos del evento, siendo el mas importante el event.target.
Todos los eventos son generados por el Flash Player son iniciados en el nivel de Stage (Escenario) y fluye hacia el componente target (capturando todos los objetos), luego alcanza el target y finalmente el evento se propaga o burbujea “Bubble” hacia los padres.
Entonces, cuando hacemos clic en un botón, podemos decir que el “event target” es el botón.
Si el botón esta dentro de un panel, el evento fluirá desde el stage al panel y luego al botón y viceversa.
Flujo del evento (II)
Ciclo de vida del evento
Fase captura
Durante esta fase, el Flash Player hace una primera pasada chequendo todos los objetos desde la raíz hasta el componente target (destino), para ver si algún componente padre podría estar interesado en procesar el evento. Por defecto, los eventos son ignorados por los padres del target.
Fase target (destino)
En esta fase, se setean las propiedades del objeto event y todos los eventos registrados para este target obtendrán este evento
Flujo del evento (III)
Ciclo de vida del evento
Fase propagacion (Bubbling)
Finalmente el evento fluye hacia atrás desde el target hasta la raiz. Para notificar a los interesados identificados en la fase de captura.
No todos los eventos tienen la fase de propagacion
Las tres fases descritas no aplican para los eventos definidos por el usuario porque Flash Player 9 no sabe o conoce las relaciones padre-hijo de los objetos eventos definidos por el usuario.
Flujo del evento (V)
Flujo del evento (VI)
Ejercicio
Comprobar fases de eventos
Revisar y ejecutar el archivo
Ejercicio_01.mxml
Estructura básica de un listener
Definir el listener y luego qué hará al detectar o escuchar el evento.
Función, que es la forma de especificar las acciones que se realizarán como respuesta al evento.
function eventResponse(eventObject:EventType):void
{
// las acciones realizadas como respuesta al evento van aquí.
}
Estructura básica de un listener (II)
Definir el nombre de la función por el nombre que se desee usar (es necesario realizar este cambio en dos lugares, donde en el código aparece eventResponse ).
Seguidamente, hay que especificar el nombre de clase adecuado para el objeto de evento distribuido por el evento que se desea detectar ( EventType en el código) y hay que indicar la constante apropiada para el evento específico ( EVENT_NAME en el listado).
En tercer lugar, es necesario llamar al método addEventListener() en el objeto que distribuirá el evento ( eventTarget en este código).
Opcionalmente, se puede cambiar el nombre de la variable utilizada como parámetro de la función ( eventObject en el código).
Flujo del evento (VII)
Ejercicio
Comprobar fases de eventos
Revisar y ejecutar el archivo
Ejercicio_02.mxml
Generalmente en la fase de captura los listener de los padres del target no son llamados, pero existe una versión del método addEventListener() que puede hacer la llamada a los listener en la fase de captura (recordemos que se hace en la fase de propagación). Para activar la llamada en la fase de captura se debe agregar un tercer argumento al método: myPanel.addEventListener(MouseEvent.CLICK, panelClickHandler, true); *No hay forma de hacerlo en MXML
Distribuir eventos (dispatch)
El método dispatchEvent() se utiliza para distribuir (gatillar) un objeto de evento personalizado en el flujo del evento.
Este método sólo acepta un parámetro, consistente en una referencia a un objeto de evento, que debe ser una instancia de la clase Event o una subclase de ésta. Una vez distribuido, la propiedad target del objeto de evento se establece en el objeto en el que se llamó a dispatchEvent().
dispatchEvent(new Event)
UFFFF!!!
Tanta teoría, vamos al grano ;-)
En resumen, se utilizaran
Dispatcher: Objeto que dispara el evento.
Event object: Objeto creado de acuerdo al tipo de evento que tiene información que puede ser compartida
Listener: Objeto que escucha y ejecuta una acción cuando detecta el evento
Formas de eventos
Formas de eventos
Definir y exponer el evento en el componente
Componente expone el evento que puede gatillar El contenedor del componente, al instanciarlo, define qué ejecutar cuando el componente gatille el evento Contenedor del evento ejecuta una función cuando detecta el evento
Formas de eventos (II)
Definir y exponer el evento en el componente (II)
Componente gatilla el evento También así
Formas de eventos (III)
Colocar un detector (listener) de eventos
El objeto o componente que desee detectar debe “inscribirse” en la lista de detectores El componente que gatilla el evento siempre lo realiza con un dispatch El componente que detecta (escucha) ejecuta la función definida
Formas de eventos (IV)
Extender la clase evento
Hay que crear una clase propia que extienda a la clase Event, heredar las capacidades de la clase Event y sobreescribir el método clone().
Formas de eventos (V)
Extender la clase evento (II)
Para colocar un detector del evento nuevo, es necesario colocar un listener Y por supuesto la correspondiente funcion handler No olvidar importar la nueva clase Para disparar el evento, es necesario el dispatcher
Práctica
Ejercicio_03
Práctica - Ejercicio_03
Funcionalidad
El usuario debe operar dos números, para ello ingresarlos, seleccionar el tipo de operación a realizar y mostrar el resultado en el campo de resultado.
Fabricar una aplicación bajo las siguientes condiciones:
Main: Contiene 3 campos de texto ( TextInput ) , 2 para ingresar los valores a operar y uno para el resultado
EL componente debe ser contenido por la aplicación principal (main)
El componente debe tener un evento que llamaremos “realizarOperacion” que será expuesto para que la aplicación que lo contiene pueda escucharlo.
En main, al instanciar el componente debemos colocar la función que se ejecutará al detectar o escuchar el evento (handling function).
En el componente, cada vez que se cierre, el (evento close) el combobox debe gatillar el evento que expone, “realizarOperacion”.
En main, la función (handler) que escucha el evento, debe tomar el valor directamente del combobox que está en el componente, jerárquicamente hacia abajo (valor = componente.combobox.selecteditem.valor), para saber que es lo que está seleccionado, una vez conocido debe realizar la operación y colocar el resultado en el campo de resultado
Hay que realizar validaciones básicas como que no se realicen operaciones sobre algo que no sea número.
Práctica - Ejercicio_03 (V) Paso 1: ingresar valores Paso 2: seleccionar operación Paso 3: mostar resultado Componente instanciado y main está preparado para gatillar una función cuando escuche el evento Combobox a la espera de del evento close, una vez ejecutado, se gatilla una funcion propia que gatilla el evento “realizarOperacion” Main detecta el evnto gatillado por el componente y obtiene el valor del combobox, evalua la operación y realiza lo indicado
Práctica - Ejercicio_03 (VI)
Ejercicio_03
Componente define y gatilla su propio evento y otro lo instancia y lo escucha.
Analizar ventajas y/o desventajas de esta solución.
Ejercicio_04
Practica - Ejercicio_04
Funcionalidad
Es necesario llevar un registro de la cantidad de operaciones que se han realizado
Condiciones
El elemento que cuenta las operaciones debe ser un componente que debe estar contenido en el componente que tiene las operaciones.
El componente debe ser un canvas con un textipunt que muestre la cuenta
Practica - Ejercicio_04 (II) Debe verse así
Practica - Ejercicio_04 (III)
Crear un nuevo componente
El nuevo componente debe escuchar el evento “sumaRealizadaEvent”
Debe estar contenido por el componente de seleccionar operador
El componente que realiza la suma debe avisar (dispatch) el evento “sumaRealizadaEvent”
Practica - Ejercicio_04 (IV)
Ejercicio_04
Un nuevo componente captura que se ha realizado una nueva operación.
Analizar ventajas y/o desventajas de esta solución.
Ejercicio_05
Practica - Ejercicio_05
Funcionalidad
Además de llevar la cantidad de operaciones realizadas, es necesario tener un elemento que nos muestre que se ha realizado una operacion
Condiciones
El elemento debe ser otro componente basado en canvas, que se encuentra contenido en el main y que tiene dentro un textarea.
Cada vez que se realice una operación (suma de la cantidad de operaciones realizadas) el texarea debe mostrar el texto “ Se ha realizado una operacion. ”, uno abajo del otro.
El evento debe ser una extension de la clase event.
Practica - Ejercicio_05 (II) Debe verse así
Practica - Ejercicio_05 (III)
Para completar este ejercicio se debe:
Crear el componente con el texarea
Crear una evento personalizado que extiende la clase event
Colocar el nuevo componente en el main
Crear un listener en el componente que tiene el texarea
Disparar el evento nuevo en el momento que se realiza la suma del total de operaciones realizadas
Practica - Ejercicio_05 (IV)
Ejercicio_05
Un nuevo componente captura un evento creado por nosotros para comunicar al usuario que se ha realizado una operación.
Analizar ventajas y/o desventajas de esta solución.
Ejercicio_06
Practica - Ejercicio_06
Funcionalidad
Además de llevar la cantidad de operaciones realizadas, es necesario llevar una lista de los resultados que se han obtenido en cada operación.
Condiciones
Debe existir un componente con una la lista, este debe ser un Datagrid con una sola columna.
Cada vez que se realice una operación (suma, resta, multiplicación) se debe guardar el resultado en la pila.
Practica - Ejercicio_06 (II) Debe verse así
Practica - Ejercicio_06 (III)
Para obtener el valor debemos crear una clase que sea capaz de obtener datos para intercambiar.
Practica - Ejercicio_06 (III)
Crear el componente con el Datagrid
Crear la nueva clase evento extendida que contenga datos
Colocar el listener en el componente creado en el creationComplete
Disparar el evento desde el que tiene el resultado de la operación
Practica - Ejercicio_06 (IV)
Ejercicio_06
Un nuevo componente muestra los datos obtenidos desde un evento.
Los datos fueron entregados al evento en el momento de su instancia
Analizar ventajas y/o desventajas de esta solución.
Y esto puede crecer y crecer.. Como diseñamos entonces para que perdamos el control?
Patrón de diseño Mediador
Patrón Mediador
Cuando los componentes se comunican entre si, mientras mas componentes hay, mas compleja es la coordinación entre ellos.
El problema de coordinación y orden entre componentes está mas que resuelto en OO.
Patrón Mediador El problema a resolver 1 2 5 3 4 6 7 8
Patrón Mediador (II)
Intención
Definir un objeto que encapsule como interactúa un conjunto de objetos.
Motivacion
Cuando muchos objetos interactúan con otros objetos, se puede formar una estructura muy compleja, con objetos con muchas conexiones con otros objetos. En un caso extremo cada objeto puede conocer a todos los demás objetos. Para evitar esto el patrón Mediator encapsula el comportamiento de todo un conjunto de objetos en un solo objeto.
Aplicabilidad
Un conjunto grande de objetos se comunica de una forma bien definida, pero compleja.
Reusar un objeto se hace difícil por que se relaciona con muchos objetos.
El comportamiento de muchos objetos que esta distribuido entre varias clases, puede resumirse en una o varias por subclasificación.
[Mediator] Patron de diseño. http://es.wikipedia.org/wiki/Mediator_%28patr%C3%B3n_de_dise%C3%B1o%29
Patrón Mediador (III) [Mediator] Patron de diseño. http://es.wikipedia.org/wiki/Mediator_%28patr%C3%B3n_de_dise%C3%B1o%29
Patrón Mediador (IV)
Participantes
Mediator ( mediador ): define una interface para comunicarse con los objetos colegas.
ConcreteMediator ("mediador concreto"): Implementa el comportamiento cooperativo entre los colegas (como se comunican entre ellos). Además los conoce y mantiene.
Colleagues ("colegas"): Cada colega conoce su mediador, y usa a este para comunicarse con otros colegas.
Colaboraciones
Los colegas envían y reciben requerimientos (requests) de un objeto mediador. El mediador implementa como se comunican los colegas
[Mediator] Patron de diseño. http://es.wikipedia.org/wiki/Mediator_%28patr%C3%B3n_de_dise%C3%B1o%29
Patrón Mediador (V)
Consecuencias El patrón Mediator tiene los siguientes beneficios y desventajas:
Desacopla a los colegas: el patrón Mediator promueve bajar el acoplamiento entre colegas. Se puede variar y rehusar colegas y mediadores independientemente
Simplifica la comunicación entre objetos: Los objetos que se comunican de la forma "muchos a muchos" puede ser remplazada por una forma "uno a muchos" que es menos compleja y más elegante. Además esta forma de comunicación es más fácil de entender.
Abstrae como los objetos cooperan: Haciendo a la mediación un concepto independiente y encapsulándolo en un objeto permite enfocar como los objetos interactúan. Esto ayuda a clarificar como los objetos se relacionan en un sistema.
Centraliza el control: El mediador es el que se encarga de comunicar a los colegas, este puede ser muy complejo, difícil de entender y modificar
[Mediator] Patron de diseño. http://es.wikipedia.org/wiki/Mediator_%28patr%C3%B3n_de_dise%C3%B1o%29
Patrón Mediador (VI)
Resumen
EL patrón mediador es un patrón de diseño que provee una interfase unificada para un set de interfaces en un subsistema.
Ejercicio_07
Práctica - Ejercicio_07
Ejercicio 07
Diseñar y fabricar el ejercicio 6 para que se convierta el un programa diseñado con el patrón mediador. Fabricar una aplicación bajo las siguientes condiciones:
Ni piense en comenzar a construir la interfaz de usuario, a menos que tengamos identificados los mediadores, componentes reusables y TODA la comunicación, por medio de eventos, entre ellos.
2 comments
Comments 1 - 2 of 2 previous next Post a comment