Patrón Observador
Un patrón de diseño es una descripción de clases y objetos comunicándose entre si adaptada para resolver un problema de diseño general en un contexto particular.
Clasificación• Propósito: Lo que realiza
• Comportamiento: Describe las formas en que las clases u objetos interactúan o distribuyen responsabilidades.
• Alcance: Donde se aplica principalmente.• Objetos: Describen como un grupo de
objetos cooperan para realizar una actividad que un objeto no puede realizar por si solo.
Intención
• Que hace:
• Definir una dependencia 1:n de manera que cuando el objeto 1 cambie su estado, los n objetos sean notificados y se actualicen automáticamente
Conocido también como
• Patrón Publicar/Suscribir
• Patrón Fisgón
• Patrón Observer
• Patrón Dependents
Contexto
• Mantener los objetos de presentación o componentes de GUI separados de los objetos de almacenamiento de datos del sistema.
• En muchas GUI’s se separan dos aspectos: los datos y la representación de esos datos
• De esta forma las clases que definen los datos y las presentaciones de las mismas pueden ser reutilizadas independientemente.
• Cuando un usuario cambia la información de los datos, todas las representaciones de esos datos deben ser actualizadas.
Motivación
● La representaciones de los datos son dependientes de los datos en si.
● No hay ninguna razón para delimitar el número de objetos dependientes.
● El patrón observer describe como establecer esta relación.
Aplicabilidad
Este patrón debe aplicarse cuando:
• Cambios en algunos de los objetos del sistema requieren cambios en otros objetos del mismo grupo.
• El número de oyentes puede variar durante el ciclo de vida del objeto.
• El bajo acoplamiento es un requerimiento básico del diseño.
Estructura
Sujeto
suscribir(Observador)eliminar(Observador)notificar()
SujetoConcreto
estadoSujeto
setEstado()
getEstado()
Para todo o en observadores{ o.actualizar();}
ObservadorConcreto
estadoObservador
actualizar() estadoObservador = sujeto.getEstado();
Observador
actualizar()
return estadoSujeto;
observadores
sujeto
Participantes
• Sujeto:
• Conoce sus observadores
• Tiene n observadores
• Provee una interfaz para agregar o eliminar observadores
• Observador
• Provee una interfaz actualizada para recibir señales del sujeto
Participantes
• Sujeto concreto
• Almacena el estado del sujeto por el cual el observador esta interesado
• Envía una notificación a su observador
• Observador concreto
• Mantiene una referencia a un objeto Sujeto Concreto
• Mantiene el estadoObservador
• Implementa la operación actualizar
Colaboraciones
setEstado()
notificar()
actualizar()
getEstado()
actualizar()
getEstado()
unSujetoConcreto unObservadorConcreto otroObservadorConcreto
Observador A Observador B
sujeto
actualizar() actualizar()getEstado()
setEstado()
Consecuencias
Ventajas• Permite reutilizar sujetos y
observadores por separado asi como añadir nuevos observadores sin modificar el sujeto o los otros observadores.
• El acoplamiento abstracto entre el sujeto y el observador ayuda a la division en niveles del sistema.
ConsecuenciasDesventajas•Todos los oyentes reciben todos los eventos lanzados, sin distinción. Esto es ineficiente, y los observadores deberían ser capaces de registrarse sólo para aquellos eventos en los que estén interesados.
•A menudo los sistemas tienen varios componentes que son generadores de eventos, y varios componentes que escuchan por esos eventos. Las relaciones entre todos estos componentes pueden ser difíciles de manejar.
Implementación
•El sujeto puede pasarse a si mismo como parametro en la notificacion de los cambios.
•Hay dos opciones según quien dispare la actualizacion
• Que las operaciones de cambio de estado del sujeto llamen automaticamente a notificar.
• que sean los observadores los que llamen a notificar. las actualizaciones son mas eficientes, pero puede que algun observador se olvide de hacerlo.
• cuando el sujeto es destruido los observadores deben ser destruidos o notificados de su destruccion.
• hay que asegurarse que el estado del sujeto es coherente antes de notificar a los observadores.
Ejemplo
Insertanotifica
sujeto* *
observadorARRAY[ ]
actualiza*
Implementación: Java
•Java provee una clase llamada Observable y una interfaz llamada Observer para poder establecer este tipo de dependencia.
•La dependencia Sujeto-Observador puede ser implementada sin necesidad de usar Observer y Observable, pero el resultado será el mismo.
•El Sujeto a ser observado debe extender de la clase Observable, y el Observador debe implementar la interfaz Observer.
Diagrama de clases
Implementación: Java
•Observer• public void update(Observabel obs, Object obj) Es invocado
cuando se produce un cambio en el estado del objeto Observable.
•Observable• public void addObservers( Observer obs ) Añade un
observador a la lista interna de observadores.
• public void deleteObservers( Observer obs ) Borra un observador de la lista interna de observadores .
• public void deleteObservers() Borra todos los observadores de la lista interna.
– public int countObserver() Devuelve el número de observadores en la lista interna.
– protected void setChanged() Levanta el flag interno que indica que el Observable ha cambiado de estado.
Implementación: Java
•Observable• protected void clearChanged() Baja el flag interno que
indica que el Observable ha cambiado de estado.
• protected boolean hasChanged() Devuelve un valor booleano indicando si el Observable ha cambiado de estado.
• public void notifyObservers() Comprueba el flag interno para ver si el Observable ha cambiado de estado y lo notifica a todos los observadores.
• public void notifyObservers( Object obj ) Comprueba el flag interno para ver si el Observable ha cambiado de estado y lo notifica a todos los observadores. Les pasa el objeto especificado en la llamada para que lo usen los observadores en su método update().
Implementación: Sujeto1 public class Sujeto{
2 private ArrayList misObservadores;
3 public Sujeto(){
4 misObservadores = new ArrayList();
5 }
6 public void suscribir(Observador obs){
7 misObservadores.add(obs);
8 }
9 public void eliminar(Observador obs){
10 misObservadores.remove(obs);
11 }
12 public void notificar(){
13 for(int i = 0; i < misObservadores.size(); i++){
14 Observador obs = (Observador)misObservadores.get(i);
15 obs.actualizar();
16 } }}
● 1 public class Fecha extends Sujeto{
● 2 private int dia, mes, anio;
● 3 public Fecha(int elDia, int elMes, int elAnio){// constructor
● 4 dia = elDia;
● 5 mes = elMes;
● 6 anio = elAnio;
● 7 System.out.println("Creado Sujeto con datos: "+dia+" "+mes+" "+anio+"\n"); }
● 8 public void setFecha(int elDia, int elMes, int elAnio){
● 9 dia = elDia;
● 10 mes = elMes;
● 11 anio = elAnio;
● 12 System.out.println("\nModifico Sujeto con datos: "+dia+" "+mes+" "+anio);
● 13 notificar(); }
● 14 public int obtenerDia(){
● 15 return dia; }
● 16 public int obtenerMes(){
● 17 return mes; }
● 18 public int obtenerAnio(){
● 19 return anio; }}
Implementación: Sujeto concreto
1 public interface Observador{
2 public void actualizar();
3 }
Implementación: Observador
1 public class VisorFechaConsola implements Observador{
2 private Fecha sujeto;
3 private int visor;
4 private String nombre;
5 public VisorFechaConsola(Fecha f, int vs, String nom){
6 sujeto = f;
7 visor = vs;
8 nombre = nom;
9 sujeto.suscribir(this);
10 }
11 public void actualizar(){
12 mostrar();
13 }
14 public void setEstado(int d, int m, int a){
15 sujeto.setFecha(d,m,a);
16 }
Implementación: Observador concreto
17 public void mostrar(){
18 int dia = sujeto.obtenerDia();
19 int mes = sujeto.obtenerMes();
20 int anio = sujeto.obtenerAnio();
21 String[] meses = {"Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"};
22 if(visor == 1){
23 System.out.println("Observador"+nombre+":("+dia+"/"+mes+"/"+anio+")");
24 }
25 if(visor == 2){
26 System.out.println("Observador"+nombre+":D("+dia+")-M("+mes+")-A("+anio+ ")");
27 }
28 if(visor == 3){
29 System.out.println("Observador " + nombre + ": " + meses[mes-1] + " " + dia + " de " + anio);
30 } } }
Implementación: Observador concreto
1 public class EjemploObservador
2 {
3 public static void main(String[] args)
4 {
5 Fecha f = new Fecha(3,10,1999);
6 VisorFechaConsola v1 = new VisorFechaConsola(f,1,"uno");
7 VisorFechaConsola v2 = new VisorFechaConsola(f,2,"dos");
8 VisorFechaConsola v3 = new VisorFechaConsola(f,3,"tres");
9 v1.mostrar();
10 v2.mostrar();
11 v3.mostrar();
12 f.setFecha(4,4,2005);
13 v2.setEstado(22,11,2005);
14 f.eliminar(v1);
15 f.setFecha(27,11,2005);
16 }}
Implementación: Ejemplo
Creado Sujeto con datos: 3 10 1999
Observador uno: (3/10/1999)Observador dos: D(3) - M(10) - A(1999)Observador tres: Octubre 3 de 1999
Modifico Sujeto con datos: 4 4 2005Observador uno: (4/4/2005)Observador dos: D(4) - M(4) - A(2005)Observador tres: Abril 4 de 2005
Modifico Sujeto con datos: 22 11 2005Observador uno: (22/11/2005)Observador dos: D(22) - M(11) - A(2005)Observador tres: Noviembre 22 de 2005
Modifico Sujeto con datos: 27 11 2005Observador dos: D(27) - M(11) - A(2005)Observador tres: Noviembre 27 de 2005
Implementación: Salida
Top Related