Está en la página 1de 10

Observer

Este patrn de diseo permite reaccionar a ciertas clases llamadas observadores sobre un evento determinado. Es usado en programacin para monitorear el estado de un objeto en un programa. Est relacionado con el principio de invocacin implcita. La motivacin principal de este patrn es su utilizacin como un sistema de deteccin de eventos en tiempo de ejecucin. Es una caracterstica muy interesante en trminos del desarrollo de aplicaciones en tiempo real.

Debe ser utilizado cuando:

Un objeto necesita notificar a otros objetos cuando cambia su estado. La idea es encapsular estos aspectos en objetos diferentes permite variarlos y reutilizarlos independientemente. Cuando existe una relacin de dependencia de uno a muchos que puede requerir que un objeto notifique a mltiples objetos que dependen de l cuando cambia su estado.

Este patrn tiene un uso muy concreto: varios objetos necesitan ser notificados de un evento y cada uno de ellos deciden como reaccionar cuando esta evento se produzca. Un caso tpico es la Bolsa de Comercio, donde se trabaja con las acciones de las empresas. Imaginemos que muchas empresas estan monitoreando las acciones una empresa X. Posiblemente si estas acciones bajan, algunas personas esten interesadas en vender acciones, otras en comprar, otras quizas no hagan nada y la empresa X quizas tome alguna decisin por su cuenta. Todos reaccionan distinto ante el mismo evento. Esta es la idea de este patrn y son estos casos donde debe ser utilizado.

Diagrama UML

Subject: conoce a sus observadores y ofrece la posibilidad de aadir y eliminar observadores. Posee un mtodo llamado attach() y otro detach() que sirven para agregar o remover observadores en tiempo de ejecucin. Observer: define la interfaz que sirve para notificar a los observadores los cambios realizados en el Subject. SubjectConcreto: almacena el estado que es objeto de inters de los observadores y enva un mensaje a sus observadores cuando su estado cambia. ObserverConcreto: mantiene una referencia a un SubjectConcreto. Almacena el estado del Subject que le resulta de inters. Implementa la interfaz de actualizacin de Observer para mantener la consistencia entre los dos estados.

Ejemplo
Vamos a suponer un ejemplo de una Biblioteca, donde cada vez que un lector devuelve un libro se ejecuta el mtodo devuelveLibro(Libro libro) de la clase Biblioteca. Si el lector devolvi el libro daado entonces la aplicacin avisa a ciertas clases que estn interesadas en conocer este evento:

Cada clase que quiera observar el cambio del estado en el libro deber implementar la siguiente interface y darle lgica al mtodo update:

Veamos el subject:

La biblioteca es quin dispara el evento. Seguramente el estado de un libro no estar en formato String, pero no viene al caso.

Veamos como funciona:

Consecuencias

Permite modificar las clases subjects y las observers independientemente. Permite aadir nuevos observadores en tiempo de ejecucin, sin que esto afecte a ningn otro observador. Permite que dos capas de diferentes niveles de abstraccin se puedan comunicar entre s sin romper esa divisin. Permite comunicacin broadcast, es decir, un objeto subject enva su notificacin a todos los observers sin envirselo a ningn observer en concreto (el mensaje no tiene un destinatario concreto). Todos los observers reciben el mensaje y deciden si hacerle caso ignorarlo. La comunicacin entre los objetos subject y sus observadores es limitada: el evento siempre significa que se ha producido algn cambio en el estado del objeto y el mensaje no indica el destinatario.

Temas a tener en cuenta.


Si los observadores pueden observar a varios objetos subject a la vez, es necesario ampliar el servicio update() para permitir conocer a un objeto observer dado cul de los objetos subject que observa le ha enviado el mensaje de notificacin. Una forma de implementarlo es aadiendo un parmetro al servicio update() que

sea el objeto subject que enva la notificacin (el remitente). Y aadir una lista de objetos subject observados por el objeto observer en la clase Observer. Si los objetos observers observan varios eventos de inters que pueden suceder con los objetos subjects, es necesario ampliar el servicio add() y el update() adems de la implementacin del mapeo subject-observers en la clase abstracta Subject. Una forma de implementarlo consiste en introducir un nuevo parmetro al servicio add() que indique el evento de inters del observer a aadir e introducirlo tambin como un nuevo parmetro en el servicio update() para que el subject que reciba el mensaje de notificacin sepa qu evento ha ocurrido de los que observa. Cabe destacar que Java tiene una propuesta para el patrn observer: Posee una Interfaz java.util.Observer: una clase puede implementar la interfaz Observer cuando dicha clase quiera ser informada de los cambios que se produzcan en los objetos observados. Tiene un servicio que es el siguiente: void update (Observable o, Object arg) Este servicio es llamado cuando el objeto observado es modificado. Adems Java nos ofrece los siguientes servicios: void addObserver (Observer o) protected void clearChanged() int countObservers() void deleteObserver (Observer o) void deleteObservers() boolean hasChanged() void notifyObservers() void notifyObservers (Object arg) protected void setChanged() Posee una clase llamada java.util.Observable: esta clase representa un objeto Subject. Veamos el mismo ejemplo con el estandard de Java:

Publicado por Maximiliano Juarez en 12:29 Etiquetas: Observer, Patrones, Patrones de Comportamiento 12 comentarios: Annimo dijo... Muchas gracias, me sirvio bastante, lo explicas de una manera muy apropiada. 27 de agosto de 2011 22:42 Leojg dijo... tengo una duda si es posible implementar observer desde otra interface. se puede? saludos. 28 de agosto de 2011 09:51 Max dijo... Muchas gracias por los comentarios. Leojg: mostre 2 formas distintas de implementar el observer: la primera con tus propias interfaces. En este caso tenes la libertad de usar las interfaces que quieras ya que las tenes que crear vos. En el 2do ejemplo, son las interfaces que nos da java. Ahi ya no

tenes tanta libertad, salvo que hagas una herencia de interface o algo asi. No se si tu pregunta se referia a eso. Saludos, Maxi 31 de agosto de 2011 14:05 Rodrigo dijo... Estimado, muy buena la explicacin, me ha sido de gran ayuda, y esta muy bueno que lo muestres de dos maneras. 19 de febrero de 2012 14:57 John Ortiz dijo... Gracias por tu trabajo. Me aclara algunos conceptos que tenan algo enlagunados. Hasta pronto. 16 de marzo de 2012 16:09 Max dijo... De nada, me alegro que les guste, pronto volvere a publicar algunas cosas en el blog. 30 de marzo de 2012 11:23 Annimo dijo... Excelente articulo, tengo una duda en el primer ejemplo, en la clase AlarmaLibro por qu es necesario que sea static el arraylist?. Gracias 15 de noviembre de 2012 17:58 Maximiliano Juarez dijo... Es static porque la idea es que haya una sola alarma en la aplicacion. Lo ideal seria que la clase sea un Singleton pero no quise ensuciar el codigo metiendo patrones dentro de patrones ya que complicaria el aprendizaje. Saludos! 16 de noviembre de 2012 07:10 Angel Zazueta Muoz dijo... Hey!!! chido chido tu cdigo, me ayud a entender mucho ms cmo aplicarlo con mis propias interfaces y con las clases que Java ofrece. Muuuchas gracias!! 18 de abril de 2013 16:23 Diego dijo...

Me gust mucho el post . Sobre todo porque mostraste una implementacin propia fuera de la que ofrece Java . Una consulta , he ledo que es vlido en el patrn MVC que la vista "observe" los cambios en el modelo . Mi duda es la siguiente , estoy haciendo una aplicacin en Swing, con las 3 capas del MVC , podra utilizar este patrn para que cuando un DAO por ejemplo inserta correctamente algo, le notifique a una vista para que esta muestre un mensaje? . Actualmente siempre retornaba algn valor desde mi Model(DAO) -> Controller -> Vista, y de acuerdo a lo que me retornaba mostraba un mensaje en mi vista. Un saludo desde Per. 29 de mayo de 2013 14:17 Maximiliano Juarez dijo... Hola Diego para este caso no creo que sea una buena idea implementar este patron. Lo ideal es trabajar bien las excepciones. Cuando la vista/controlador llaman a modelo este debe devolver el objeto indicado. En caso que algo no salga bien, entonces deberia devolver una excepcion con un mensaje de error apropiado para que pueda mostrar la vista. En tu caso particular, por lo general los inserts suelen ser void. Calculo que con tener un metodo void que lanze una o mas excepciones seria suficiente. 31 de mayo de 2013 10:55 Diego dijo... Comprendido . Muchas gracias!. Espero que sigas actualizando el blog que est interesante . Un saludo! 31 de mayo de 2013 11:41

También podría gustarte