Páginas

jueves, 11 de septiembre de 2014

Ejemplo de programa orientado a eventos

Ejemplo de programa orientado a eventos

En este ejemplo vamos a ver como programar usando eventos y observadores.  Se basa en que cuando se produce un evento en un objeto del programa, este evento se propaga por toda la aplicación haciendo que los objetos que lo estuvieran observando  ejecuten el código que tengan asociado a dicho evento.



Eston son los comandos que vamos a usar:
Event: es un comando que hace que se declare un evento dentro de una clase (ver http://gambaswiki.org/wiki/lang/eventdecl?l=es&w )
EVENT Nombre ( [ Parámetro #1 [ , Parámetro #2 ... ] )
Raise: es un comando que hace que se dispare el evento. (ver http://gambaswiki.org/wiki/lang/raise?l=es&w )

[ Cancelado = ] RAISE Evento ( [ Parámetro #1 [ , Parámetro #2 ... ] )

Observer: Los Observadores son objetos que le permiten interceptar eventos lanzados por otros objetos, es decir que los "observan". (ver http://gambaswiki.org/wiki/comp/gb/observer/_new?l=es&w )

hObserver = New Observer ( Object As Object [ , After As Boolean ] )



Nuestro Ejemplo:



Tenemos varios objetos "peloton" los cuales cuando son atacados (evento atacar), informan a sus superiores (que los estan observando), para que tomen las acciones adecuadas.





 Este es el código de la clase Pelotón:
' gambas class file

Event ataque(obj As Object, dato As Point)
Private posicion As New Point

Public Sub _new(xx As Integer, yy As Integer)
'posicion en el tablero

posicion.X = xx
posicion.y = yy

End

Public Sub SiendoAtacado()

Raise ataque(Me, posicion)

End



Como veis, hemos declarado un evento, "ataque", que acepta los parametros obj (un objeto) y dato (una coordenada)
Cuando se ejecuta el método "SiendoAtacado()", este hace que se dispare en el programa, el evento ataque, pasando los datos (parámetros) el propio objeto (ME) y su posicion.


Ahora vemos,la clase ControlDeTropas:
' gambas class file

Private ObservadorControl2 As Observer

Public Sub _new()

End

Public Sub addObservador(p As Peloton)

ObservadorControl2 = New Observer(p) As "Observador"

End

Public Sub Observador_ataque(obj As Object, d As Point)

Print "Posicion atacada (evento desde objeto): ", obj, d.x, d.y

End




Comentamos el código:
Lo primero que hacemos es definir un observador: ObservadorControl2
Luego tenemos el metodo publico .addObservador, que tiene como parámetro a un objeto peloton, y que lo que hace es crear un observador al objeto pasado , agrupandolo en "Observador"

"Observador" tiene ahora un evento "_ataque", que recibe los datos del objeto y de la posición (los datos que manda Raise). Y nos presenta un texto por pantalla. Esto  de escribir un mensaje, es una simplificación, no normal seria que hiciera algo: mandar ayuda (otro peloton) a esa posición, etc


La clase ServiciosSanitarios:
' gambas class file

Private ObservadorControl As Observer

Public Sub _new()

End

Public Sub addObservador(p As Peloton)

ObservadorControl = New Observer(p) As "Observador"

End

Public Sub observador_ataque(obj As Object, d As Point)

Print "Posicion que tengo que enviar ayuda (evento desde objeto): ", obj, d.x, d.y

End



Esta clase es muy similar a la anterior, lo que cambia es la acción que realizará cuando se produzca el evento  _Ataque(), ya que nos muestra distitno mensaje

El principal Fmain
:

' gambas class file

Public cTropas As ControlTropas
Public ServSani As ServiciosSanitarios
Public ptmp As Peloton
Public listaPelotones As New Peloton[]

Public Sub _new()

End

Public Sub Form_Open()

cTropas = New ControlTropas
ServSani = New ServiciosSanitarios

ptmp = New Peloton(10, 243)
listaPelotones.add(ptmp)
ptmp = New Peloton(130, 3)
listaPelotones.add(ptmp)
ptmp = New Peloton(-2, -53)
listaPelotones.add(ptmp)

For Each ptmp In listaPelotones
cTropas.addObservador(ptmp)
ServSani.addObservador(ptmp)
Next

End

Public Sub Button1_Click()

Dim p As Peloton

If RadioButton1.value = True Then p = listaPelotones[0]
If RadioButton2.value = True Then p = listaPelotones[1]
If RadioButton3.value = True Then p = listaPelotones[2]

p.SiendoAtacado()

End


En el programa pincipal, cuando se abre el formulario (_open() ) se crea una lista de objetos pelotones. y estos se van añadiendo a los objetos cTropas y ServSani, para que los observen.

Si se elige a un peloton dependiendo del radiobutton seleccionado. elegido y se pulsa el boton del formulario (button1_click) , , se llama al método ".siendoAtacado" del peloton seleccionado.

De una manera "trasparente" .siendoAtacado, hace que se dispare el evento Ataque, y que los objetos que observan al peloton elegido, respondan y manden los mensajes.


En el siguiente video podemos ver como se ejecuta el programa y lo que se va obteniendo.


¿que utilidad tiene todo esto? Imaginaos que creamos otra clase "X" que tambien va a observar y hacer algo cuando un peloton sea atacado....solo con  añadir el código de la nueva clase, y modificando el bucle For Each,  para que observen los objetos pelotones por el objeto "X", podemos ampliar el código, sin tocar el resto del programa:

For Each ptmp In listaPelotones
cTropas.addObservador(ptmp)
ServSani.addObservador(ptmp)

'.....aqui se pueden añadir los  nuevos objetos que observen a ptmp
Next




'Codigo fuente de ejemplo:
https://drive.google.com/file/d/0B02Ro2CNt-OOSjUtc2RGRG1OS00/edit?usp=sharing
https://drive.google.com/file/d/0B02Ro2CNt-OOQUw0UnhZdEV2c3c/edit?usp=sharing

El 2º enlace es un ejemplo ampliado, añadiendo un nuevo observdor al formulario

Nota:
Todo lo anteriormente dicho, se trata de la forma que tiene gambas3 de aplicar el patron observador.
Como vereis es más simple ya que nos proporciona todas las herramientas para aplicarlo.


Fuente:
http://gambaswiki.org/wiki/doc/object-model?l=es
http://www.gambas-es.org/viewtopic.php?f=1&t=3960&highlight=eventos