domingo, 23 de junio de 2013

Ejemplo Patrón Observer

Vamos a realizar un pequeño y muy común ejemplo sobre el Patrón Observer....... en la entrada sobre Patrones de Diseño tocamos en términos generales que hace el patrón y como podríamos utilizarlo, (si no la han visto los invito a visitarla) en esta ocasión repasaremos un poco sobre su estructura he implementación y posteriormente daremos inicio al ejemplo.....

¿Que es?

Básicamente debemos saber que el patrón Observer es un patrón de comportamiento que permite relacionar diferentes objetos entre si en torno a uno Principal, así cada vez que este ultimo cambie su estado, los demás también cambiaran de forma automática....

Podemos decir entonces que dicho patrón se compone de un objeto observable u Observado (SujetoConcreto) y objetos observadores (ObservadorConcreto)....

Un  Objeto Observable puede tener uno o mas Observadores, como vemos el ObservadorConcreto implementa la interface Observer (propia de Java) la cual permite informar sobre los cambios en los objetos observables mediante una llamada al método update()...

java también nos proporciona la Clase Observable de la cual extienden las clases o sujetos concretos (los observados), esta clase provee varios métodos importantes como por ejemplo registerObserver(), removeObserver(), notifyObservers() entre otros necesarios para el funcionamiento del patrón, mas adelante en nuestro ejemplo veremos como lo podemos usar.


El Problema.

Nos solicitan desarrollar una paleta de colores donde el usuario1 pueda seleccionar y visualizar el color que le guste, a la vez dicha selección debe ser controlada en tiempo real por el usuario2 y el usuario3 que hacen seguimiento a la selección realizada, el problema radica en que estos usuarios se encuentran en habitaciones distintas y no pueden ver la selección del usuario1...

La Solución.

Aplicaremos el Patrón Observador ya que según la solicitud, los usuarios 2 y 3 deben ser informados de manera automática sobre la selección del usuario1, (esto descarta la posibilidad de que ambos usuarios tengan que refrescar el sistema, pantalla o ventana para estar al tanto del color elegido por el usuario1) de esta forma podríamos definir que el usuario1 sera el observado y los demás los observadores.............sin embargo podemos manipular nuestra solución para que todos tengan ambos roles.


La Aplicación.

Crearemos 3 Ventanas que presentarán las aplicaciones de los usuarios, dichas ventanas implementarán las interfaz Observer, siendo cada una un ObservadorConcreto,  tenemos también la ClaseObservador la cual extenderá de la clase Observable siendo así el sujetoConcreto, pero como mencionamos anteriormente vamos a hacer que todas las aplicaciones de los usuarios tengan ambos roles, para esto asociaremos a las clases "Ventanas" con la ClaseObservador mediante instancias de esta ultima y de esta forma nuestras clases Ventanas serán tanto Observadores Concretos como Sujetos Concretos, donde el rol dependerá de la función de cada una...


ClaseObservador.

Esta clase sera el medio por el cual las clases VentanaSelección, VentanaColor, y VentanaOpciones podrán convertirse en SujetosConcretos (Usando métodos set y get...)...........la claseObservador extiende de Observable heredando los métodos requeridos para notificar a los observadores sobre los cambios realizados, para esto usaremos el atributo colorSeleccionado activando los eventos de setChanged() y notifyObservers()

public class ClaseObservador extends Observable{
 
 private int colorSeleccionado;
 private String color;
 
 public ClaseObservador(){
  
 }
 public void setColorSeleccionado(int i) {
  this.colorSeleccionado = i;
  setChanged();
     notifyObservers();
 }
 public int getColorSeleccionado() {
  return colorSeleccionado;
 }
 public void setColor(String color) {
  this.color = color;
 }
 public String getColor() {
  return color;
 }
}


Clase Principal.

Esta sera la clase encargada de dar inicio al sistema, además en ella también estableceremos las relaciones entre la ClaseObservador y las Clases "Ventanas", crearemos instancias de cada Clase y luego mediante el método addObserver() (Heredado de Observable) agregaremos todos los ObservadoresConcretos a nuestro SujetoConcreto.

public static void main(String[] args) 
{
  ClaseObservador observador=new ClaseObservador();
  VentanaOpciones miVentanaOpciones=new VentanaOpciones(observador);
  VentanaColor miVentanaColor=new VentanaColor(observador);
  VentanaSeleccion miVentanaSeleccion=new VentanaSeleccion(observador);
 
  /**Aqui se Agregan los observadores*/
  observador.addObserver(miVentanaColor);
  observador.addObserver(miVentanaSeleccion);
  observador.addObserver(miVentanaOpciones);
}

VentanaColor.

Esta será la clase que simulará la aplicación manejada por el usuario1, esta clase implementará la interfaz Observer y definirá el comportamiento del método update() que como mencionamos anteriormente es llamado cada vez que la ClaseObservador cambia de estado, también crearemos una instancia de dicha clase para convertir a VentanaColor en un SujetoConcreto y de esta forma las demás ventanas serán informadas cuando esta cambie mediante los eventos definidos por el usuario....

VentanaOpciones.

Esta clase corresponde a la aplicación del usuario2, brindaremos la opción al usuario de seleccionar algún color, en esta clase también definimos una instancia de ClaseObservador de modo que por medio del evento generado y la instancia mencionada podamos dar un comportamiento de SujetoConcreto, igual que la anterior también implementa la interfaz Observer...(El combo se actualiza si el usuario1 cambia de color)

VentanaSelección.

Representa la aplicación del usuario3, esta ventana a diferencia de las anteriores no posee ninguna opción disponible para el usuario, tan solo cumplirá el rol de ObservadorConcreto, posee una instancia de ClaseObservador mediante la cual estará informando al usuario sobre la opción seleccionada en alguna de las ventanas, todo esto gracias al método update() de la interfaz Observer.


Conclusiones.

Y Listo!!!...............Como vemos el ejemplo es muy básico, no tenemos paquetes ni cosas complejas, solo se busca cumplir con el objetivo de dar a entender la aplicación del patrón Observer, simulamos las ventanas como 3 aplicaciones diferentes, sin embargo este patrón también puede ser combinado con diferentes proyectos para hacer mucho mas real su aplicación.


Referencias.

Head First Design Patterns

Descarga.

En el link de descarga se encuentra el archivo .rar con la aplicación, solo es cuestión de descomprimir y abrir con Eclipse pero si usas NetBeans te interesará esta entrada con un vídeo paso a paso de como abrirlo en el........... [recuerden que es gratis.....nada cuesta opinar, compartir o agradecer :)]

Espero que este ejemplo sea de Utilidad y sirva como base para su aplicación en futuros desarrollos ;)




También te podría Interesar. 


¿Hay algo que quieras anexar o comentar sobre esta entrada?  no dudes en hacerlo.....y si te gustó, te invito a compartir y Suscribirte ingresando al botón "Participar en este sitio" para darte cuenta de mas entradas como esta ;)

30 comentarios:

  1. muy interesante trabajo!...

    lo voy compartiendo con mis compañeros de trabajo para que vayan aprendiendo tambien

    ResponderEliminar
    Respuestas
    1. Gracias, esa es la idea, que el conocimiento sea compartido!!!

      Eliminar
    2. Tenia algunos errores, como por ejemplo daba la opcion de "naranja" solo en una de las ventanas, en la otra no aparecia... pero nos servira igual para el trabajo que tenemos que presentar :D lo modifique un poco pero gracias igual por el codigo :3

      Eliminar
  2. Hola Cristian me pareció bastante bueno el ejemplo y la forma en como lo encaraste por lo que lo hace bastante entendible a la explicacion.
    Tengo una duda este patrón se puede aplicar con juegos que se realizan por turno,mediante las imagenes(misil,tanque,etc) y coordenadas(de la imagen)? y como se encararía si existe una posibilidad aunque sea en un diagrama de objetos.desde ya gracias por el post.
    Saludos
    Héctor

    ResponderEliminar
    Respuestas
    1. Hola veo que estuviste muy ocupado este tiempo....
      lo pude solucionar de otra manera, gracias de todas formas muy buen tutorial
      Saludos
      Héctor

      Eliminar
    2. Hola Hector, que pena contigo, la verdad si he estado un poco ocupado pero bueno, es interesante lo que planteas, la verdad no se me habia pasado por la mente pero yo creeria que si se podria trabajar asi, en este ejemplo enviamos los valores de cada color, yo creo que se podria trabajar similar, enviando coordenadas como tu dices y que cada observador las identifique...... seria muy bueno saber como lo solucionaste?... Un saludo ;)

      Eliminar
    3. Hola Cristian
      Al final utilice el patron MVC.
      Lo hice con vectores de objetos de esa forma lo mandaba a un método.
      En el proyecto implemente eventos del Keypresed e identificación de salud y threads con imágenes y sonidos. igual era un prototipo para un examen, mas adelante si tengo tiempo voy a ver como implementar el Singleton para las llamadas al sonido e imágenes de fogoneo,destruido,averiados y Observer para notificacion de estados destruido, averiado,ganador,perdedor,etc.
      Saludos
      Héctor

      Eliminar
  3. Gracias por el ejemplo, entendía la teoria pero no me lo imaginaba en código.
    Saluods

    ResponderEliminar
  4. Gracias por compartir la información Cristian.

    Estoy leyendo acerca de los patrones que has escrito y esta bien interesante.

    Trate de descargar el proyecto del patrón Observer, pero no me deja, no muestra ningún error ni nada por el estilo, solamente no lo descarga. Me imagino que ya no esta disponible el ejemplo.
    Si pudieras re subir el ejemplo del patrón observer te lo agradecería mucho.

    Disculpa las molestias.

    Gracias y saludos amigo.

    Edgar Mayorga

    ResponderEliminar
    Respuestas
    1. Hola Edgar, gracias por avisarme, no se que pasó con la plataforma pero efectivamente no se podian bajar, por eso me pasé a Mega y ya actualicé el enlace...... un saludo y espero que te sirva ;)

      Eliminar
  5. Muchas gracias Cristian, que Dios te bendiga.
    Voy a estudiar tu código y gracias por subirlo nuevamente.

    Gracias.

    ResponderEliminar
    Respuestas
    1. Edgar con mucho gusto, me alegra que le sirviera ;)

      Eliminar
  6. Es recomendable utilizar 2 observers ?
    Por ejemplo, tengo una clase "ListaDeMails" que tiene 2 metodos "altaUsuario" y "bajaUsuario".
    Yo quiero que el observer "A" se active cuando sucede el evento de alta, y notifique a toda la lista de mails.
    Y quiero un observer "B" que se active cuando sucede el evento de alta para que notifique solo al administrador.
    Es correcta mi forma de pensar de 2 observer?

    ResponderEliminar
    Respuestas
    1. Hola, yo creería que no hay inconveniente en lo que mencionas ya que la aplicación del patrón depende de lo que necesites, si ves en el ejemplo un observable puede ser un observador también entonces podría servirte......... un saludo

      Eliminar
    2. Muchisimas gracias Cristian.

      Eliminar
  7. Hola, interesante tu propuesta simple pero precisa, tengo una duda, en vez de colores, como lo plantearias con imagenes?, saludos

    ResponderEliminar
    Respuestas
    1. Hola Diego, así rapidamente podria ser igual, que cada ventana tenga una imagen en un panel y que permita modificarla en cada una, si selecciono el combo por ejemplo, en esa ventana se actualice así como en las otras.

      Eliminar
  8. Hola Cristian.
    Ante todo muchas gracias por compartir todo lo que sabes con los demás, a mi personalmente me ha ayudado mucho haber encontrado tu blog y poder extraer información y conocimientos de él.

    Quería comentarte una duda. Estoy creando una aplicación de entrada de pedidos de compras. La típica JTable para ir entrando referencias de compras e ir grabando en la tabla de la bd de pedidos, En la cabecera de la pantalla también hay campos para poder introducir el proveedor, el número y la fecha del pedido y algunas cosas más.
    Ésta pantalla me sirve tanto para las altas, como para modificaciones y bajas de pedidos.
    En el caso de altas no es problema, pues utilizando el modelo MVC lo soluciono, pero cuando deseo cargar un pedido ya existente en la bd desde la pantalla tecleando el número de pedido, llamo a las métodos correspondientes de las clases tipo controlador, logica y DAO, En la clase DAO finalmente se realiza la select de la bd para que se extraigan los datos, pero a partir de aquí ¿como lo hago para que los datos se carguen en la JTable de la vista y ésta se refresque? ¿Es correcto mezclar en una misma aplicación el patrón MVC y el patrón Obeserver?

    Disculpa por tanta palabrería mía, espero haberme explicado bien, aunque no de manera muy resumida.

    Saludo y muchas gracias.

    ResponderEliminar
    Respuestas
    1. Hola, que pena la hora de responderte solo que he estado muy apretado de tiempo.....rapidamente te podria comentar que (no se si lo haces) para refrescarlo nuevamente creeria que puedes solucionarlo instanciando cada vez el objeto con los datos que cargas en el jtable (puede ser un objeto o una lista, depende de como lo manejes)..........y no hay problema en mezclar patrones, es muy común que se vinculén mas de uno.

      Eliminar
    2. Hola de nuevo.
      No pasa nada, te entiendo con lo de estar ocupado.
      Al final opté por como dices refrescar la lista de datos instanciando de nuevo el objecto
      Muchas gracias por todo.

      Saludos.

      Eliminar
  9. HHoola gracias por ejemplo muy buena explicacion que se completa con el codigo!!

    ResponderEliminar
  10. Muchas gracias una muy buena explici'on del patrón observer

    ResponderEliminar
  11. Wow!!! muy buen ejemplo gracias, me ha ayudado a entender este patron de diseño

    ResponderEliminar
  12. Saludos Cristian,
    Tu blog ha sido de mucha ayuda, ya que encaras los problemas de una manera sencilla y muy didactica además que tus temas son muy acertados. Muchas gracias por explicar este patrón.
    Una pregunta, tu empleas las clases propias de java, observable y la interfaz observer. Podemos hacer nuestra propia clase?

    ResponderEliminar
  13. Cristian! Muchas gracias por crear esta página. Me ha sido de mucha ayuda para entender Java de manera más amena (al igual que los videos que tienes en youtube :) )
    Pequeña pregunta: puedo ocupar este patrón para manipular choices?

    Es decir, si tengo 3 choices en "una" ventana (en vez de tener 3 ventanas como en el ejemplo que acá se da), y lo que quiero es que si los 3 despliegan las mismas opciones; si selecciono una opción en el primer choice... en el segundo y tercer choice esa opción ya no pueda seleccionarse?

    De antemano, muchas gracias de nuevo :)

    ResponderEliminar
  14. Muy buena la explicación, gracias

    ResponderEliminar
  15. Eres el mejor del mundo mundial ! , Dios te Bendiga y ojala sigas ayudando a los más necesitados, de verdad Ha-ha.

    ResponderEliminar
  16. es excelente el tutorial, aunque tengo unos vacíos, voy a probar el ejercicio en net beans y le informo, muchas gracias

    ResponderEliminar

Eres libre de realizar cualquier comentario, desde que pueda ayudar con gusto lo atenderé, y si es un critica, bienvenida sea!!!