Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa...

22
Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto

Transcript of Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa...

Page 1: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Patrones de Comportamiento: Patrón de

Diseño Observer

David Inocente Romero Escalona

Rosa Hernández AliasJacinto José Cruz Nieto

Page 2: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Patrones de Comportamiento Chain of Responsibility Command Interpreter Iterator Mediator Memento Observer State Strategy Template Method Visitor

Page 3: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Patrón Observer Define una dependencia entre objetos de

uno (subject) a muchos (observers). Unos ciertos eventos son notificados por el

subject a todos los observers que dependen de él, lo cuales realizan una cierta tarea en consecuencia.

Establece dos comportamientos comunes: Uno entre todos los objetos subjects. Otro entre todos los objetos observers.

Para ello usa dos clases abstractas: Subject y Observer.

Page 4: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Patrón Observer Este patrón (algunas veces conocido como

editor/subscriptor) es un patrón de diseño usado en programación para observar el estado de un objeto en un programa. Está relacionado con el principio de invocación implícita.

Está usado como un sistema de detección de eventos. Es una característica muy interesante en términos del desarrollo de aplicaciones en tiempo real.

Page 5: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Objetivos 1. Reducir al mínimo el acoplamiento entre las

clases a las que pertenecen los objetos subjects y observers para aumentar la reusabilidad de dichas clases.

Para ello se usa las clases abstractas Subject y Observer, que crean un primer nivel de abstracción en el que se incluyen todas las dependencias entre clases para que las clases concretas que heredan de ellas sean lo más independientes posibles.

2. Permitir un número ilimitado de objetos observers que observen a un cierto objeto subject.

Para ello la clase abstracta Subject tiene una lista de objetos observers a los que notificar en caso de que suceda algún evento de interés.

Page 6: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Diagrama de clases UML para el patrón Observer básico

Page 7: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Diagrama de clases UML para el patrón Observer básico Subject: notificador de eventos. Observer: observador de eventos. En el diagrama se presuponen varias condiciones:

Existe un único evento de interés (que el estado de un objeto subject cambie).

La tarea que llevan a cabo los objetos observers cuando sucede ese evento de interés es actualizar su estado con el estado actual del objeto subject que observan.

Cada objeto observer observa a un único objeto subject. Son los objetos subject los responsables de enviarse así

mismos el mensaje notify() cuando cambian sus estados (y no son responsables los objetos observers cuando modifican el estado de su objeto subject).

Page 8: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Diagrama de clases UML para el patrón Observer básico El funcionamiento básico es:

1. Algún objeto modifica el estado de un objeto ConcreteSubject enviando el mensaje setState() a dicho objeto (se produce un evento de interés).

2. El objeto ConcreteSubject cambia su estado y se envía a sí mismo el mensaje notify(), con lo que notifica a todos los objetos observers de su lista (a todos los que le observan) enviándoles el mensaje update().

3. Los objetos notificados serán de una clase ConcreteObserver que hereda de Observer. Al recibir el mensaje update(), consultarán el estado del objeto ConcreteSubject que les envió la notificación (enviándole el mensaje getState()) y actualizarán su propio estado con el resultado obtenido (los objetos observers llevan a cabo la tarea correspondiente al evento de interés que se ha producido).

Page 9: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Diagrama de clases UML para el patrón Observer básico Cuando el evento es lanzado cada observador recibe una

callback. Cuando un observador concreto es informado de un cambio en

el sujeto concreto, éste puede pedirle al sujeto más información que será usada para actualizar su estado.

Page 10: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Patrón Observer: aplicabilidad Una abstracción tiene dos aspectos y uno

depende del otro. (Encapsular estos aspectos en objetos separados permite modificarlos y reutilizarlos de forma independiente)

Un cambio en un objeto requiere cambiar otros, y no sabemos cuántos objetos necesitan cambiarse.

Un objeto debería ser capaz de notificar a otros sin hacer suposiciones sobre quiénes son dichos objetos. Es decir no queremos que los objetos estén fuertemente acoplados.

Page 11: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Ventajas y desventajas del patrón Observer básico Ventajas:

Permite modificar las clases subjects y las observers independientemente. Se pueden rehusar clases subjects sin rehusar sus clases observers.

Permite añadir nuevas clases observers a una clase subject que ya tenía asociadas unas clases observers sin modificar la clase subject o alguno de esas clases observers que ya tenía.

Permite que dos capas de abstracción de diferentes niveles de abstracción se puedan comunicar entre sí sin romper esa división en capas de abstracción. Por ejemplo, en el caso de las capas de Presentación y Dominio.

Permite comunicación broadcast, es decir, un objeto subject envía su notificación a todos los objetos observers que lo estén observando sin enviárselo a ningún observer en concreto (el mensaje no tiene un destinatario concreto). Todos los observers reciben el mensaje y deciden si hacerle caso ó ignorarlo.

Page 12: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Ventajas y desventajas del patrón Observer básico Desventajas:

El protocolo de comunicación entre los objetos subject y sus objetos observers es muy pobre: el evento siempre es que se ha producido algún cambio en el estado del objeto subject, el mensaje no indica el destinatario (siempre es broadcast) y tampoco indica qué es lo que ha cambiado en el objeto subject (y, entonces, son sus objetos observers los que tienen que deducir qué es lo que ha cambiado en el objeto subject sin ayuda de éste, si así lo desean; lo que puede introducir gran complejidad computacional en los observers).

Aumenta el número de clases necesarias para implementar la aplicación y disminuye la comprensibilidad de ésta.

Los observers dependen del subject al que observan, pues lo conocen (hacen referencia a él), por lo que cambios en la clase del subject pueden provocar cambios en las de los observers.

Page 13: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Notas de implementación Si los objetos observers pueden observar a varios objetos subject a la vez, es

necesario ampliar el servicio update() para permitir conocer a un objeto observer dado cuál de los objetos subject que observa le ha enviado el mensaje de notificación.

Una forma de implementarlo es añadiendo un parámetro al servicio update() que sea el objeto subject que envía la notificación (el remitente). Y añadir una lista de objetos subject observados por el objeto observer en la clase Observer.

Hay dos opciones en cuanto a qué objeto invoca el servicio notify(): El objeto subject: todos los servicios de la clase Subject que modifican el estado del objeto

subject envían el mensaje notify() reflexivamente (patrón Observer básico). Ventaja: Los observers no tienen que recordar invocar a notify() cuando modifican el estado de un objeto

subject. Desventaja: sucesivos cambios de estado de un objeto subject provocan sucesivas llamadas a notify(), lo que

puede ser ineficiente. El objeto observer: decide cuándo es necesario enviar el mensaje notify() a su objeto subject y

se lo envía en ese momento. Ventaja: Los objetos observers deciden cuándo invocar a notify(), permitiendo realizar sucesivos cambios en el

estado de un objeto subject y realizando un única invocación a notify() al final, lo que es más eficiente. Desventaja: Los observers tienen la responsabilidad de invocar a notify(), por lo que tienen que recordar

hacerlo. Si los objetos observers observan varios eventos de interés que pueden suceder

con los objetos subjects, es necesario ampliar el servicio add() y el update() además de la implementación del mapeo subject-observers en la clase abstracta Subject (que tiene que incluir la información de qué evento está observando cada observer).

Una forma de implementarlo consiste en introducir un nuevo parámetro al servicio add() que indique el evento de interés del observer a añadir e introducirlo también como un nuevo parámetro en el servicio update() para que el subject que reciba el mensaje de notificación sepa qué evento ha ocurrido de los que observa.

Page 14: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Clases en la API de Java para implementar el Patrón Observer

Interfaz Observer public interface 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.

Page 15: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Clases en la API de Java para implementar el Patrón Observer

Class Observable public Class Observable extends

Object Esta clase representa un objeto Subject,

o “dato” en el modelo vista. Constructor:

Observable () : construye un objeto Subject con cero Observers.

Page 16: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Clases en la API de Java para implementar el Patrón Observer

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()

Page 17: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Ejemplo Se trata de una aplicación que almacena una serie de datos,

tres números enteros (a, b y c), y los representa en pantalla.

Page 18: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Ejemplo (diagrama de clases UML con el patrón Observer básico)

Page 19: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Ejemplo (código Java)public abstract class Subject{

private List<Observer> observers;public void add(Observer o){

this.observers.add(o);}public void remove(Observer o){

this.observers.remove(o);}public void notify(){

for (int i = 0; i<this.observers.size(); i++)

this.observers.get(i).update();}public Subject(){

this.observers = new ArrayList<Observer>();}

}

public abstract class Observer{

private Subject subject;protected Subject getSubejct(){

return this.subject;}public Observer(Subject s){

this.subject = s;}public abstract void update();

}

Page 20: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Ejemplo (código Java)public class Dominio extends Subject{

private double a, b, c;public Dominio(double[3] s){

super();this.a = s[0];this.b = s[1];this.c= s[2];

}public double[3] getState(){

double[3] s = new double[3];

s[0] = this.a;s[1] = this.b;s[2] = this.c;return s;

}public void setState(double[3] s){

this.a = s[0];this.b = s[1];this.c= s[2];this.notify();

}}

public class Vista1 extends Observer{

private double[][] tabla = new double[3][3];private int sig = 0;public Vista1(Dominio d){

super(d);this.update();

}public void update(){

double[3] s = ((Dominio).getSubject()).getState();

this.tabla[sig] = s;sig = (sig+1)%3;this.redibujar();

}}

Page 21: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Ejemplo (código Java)

public class Vista2 extends Observer{

private double a, b, c;public Vista2(Dominio d){

super(d);this.update();

}public void update(){

double[3] s = ((Dominio)getSubject()).getState();

a = s[0];b = s[1];c = s[2];this.redibujar();

}}

public class Vista3 extends Observer{

private double a, b, c;public Vista3(Dominio d){

super(d);this.update();

}public void update(){

double[3] s = ((Dominio)getSubject()).getState();

a = s[0];b = s[1];c = s[2];this.redibujar();

}}

Page 22: Patrones de Comportamiento: Patrón de Diseño Observer David Inocente Romero Escalona Rosa Hernández Alias Jacinto José Cruz Nieto.

Patrones Relacionados

Se pueden encapsular semánticas complejas entre subjects y observers mediante el patrón Mediator.

Dicha encapsulación podría ser única y globalmente accesible si se usa el patrón Singleton.