patterns pattern observer mvc dzone java design-patterns observable observer-pattern observers

mvc - observer pattern java



Cuándo deberíamos usar Observer y Observable (10)

Un entrevistador me preguntó:

¿Qué es Observer y Observable y cuándo deberíamos usarlos?

No estaba al tanto de estos términos, así que cuando volví a casa y comencé a buscar en Google Observer y Observable encontré algunos puntos de diferentes recursos:

1) Observable es una clase y Observer es una interfaz.

2) Clase Observable mantener una lista de observadores.

3) Cuando se actualiza un objeto Observable, invoca el método update() de cada uno de sus observadores para notificar que se ha modificado.

Encontré este ejemplo:

import java.util.Observable; import java.util.Observer; class MessageBoard extends Observable { public void changeMessage(String message) { setChanged(); notifyObservers(message); } } class Student implements Observer { @Override public void update(Observable o, Object arg) { System.out.println("Message board changed: " + arg); } } public class MessageBoardTest { public static void main(String[] args) { MessageBoard board = new MessageBoard(); Student bob = new Student(); Student joe = new Student(); board.addObserver(bob); board.addObserver(joe); board.changeMessage("More Homework!"); } }

Pero no entiendo por qué necesitamos Observer y Observable ? ¿Para qué sirven los setChanged() y notifyObservers(message) ?



El patrón de observador se usa cuando hay una relación de uno a varios entre los objetos, como por ejemplo si un objeto se modifica, sus objetos dependientes se notificarán automáticamente.


En términos muy simples (porque las otras respuestas lo remiten a todos los patrones de diseño oficiales de todos modos, así que mírelos para obtener más detalles):

Si desea tener una clase supervisada por otras clases en el ecosistema de su programa, diga que desea que la clase sea observable. Es decir, puede haber algunos cambios en su estado que desee transmitir al resto del programa.

Ahora, para hacer esto tenemos que llamar a algún tipo de método. No queremos que la clase Observable esté estrechamente unida a las clases que están interesadas en observarla. No le importa quién es, siempre que cumpla con ciertos criterios. (Imagine que es una estación de radio, no importa quién esté escuchando, siempre y cuando tengan una radio FM sintonizada en su frecuencia). Para lograr eso, usamos una interfaz, conocida como Observer.

Por lo tanto, la clase Observable tendrá una lista de Observadores (es decir, instancias que implementen los métodos de interfaz del Observador que pueda tener). Cada vez que quiere transmitir algo, simplemente llama al método sobre todos los observadores, uno después del otro.

Lo último para cerrar el rompecabezas es ¿cómo sabrá la clase Observable quién está interesado? Entonces la clase Observable debe ofrecer algún mecanismo para permitir a los Observadores registrar su interés. Un método como addObserver(Observer o) internamente agrega el Observer a la lista de observadores, de modo que cuando sucede algo importante, recorre la lista y llama al respectivo método de notificación de la interfaz Observer de cada instancia en la lista.

Es posible que en la entrevista no le hayan preguntado explícitamente sobre java.util.Observer y java.util.Observable sino sobre el concepto genérico. El concepto es un patrón de diseño, que ofrece compatibilidad con Java directamente desde el inicio para ayudarlo a implementarlo rápidamente cuando lo necesite. Por lo tanto, sugiero que comprenda el concepto en lugar de los métodos / clases reales (que puede consultar cuando los necesite).

ACTUALIZAR

En respuesta a su comentario, la clase real java.util.Observable ofrece las siguientes instalaciones:

  1. Mantener una lista de instancias de java.util.Observer . Las nuevas instancias interesadas en ser notificadas pueden agregarse a través de addObserver(Observer o) y eliminarse mediante deleteObserver(Observer o) .

  2. Mantener un estado interno, especificando si el objeto ha cambiado desde la última notificación a los observadores. Esto es útil porque separa la parte donde dice que el Observable ha cambiado, desde la parte donde notifica los cambios. (Por ejemplo, es útil si tiene varios cambios y solo desea notificar al final del proceso en lugar de hacerlo en cada paso). Esto se hace a través de setChanged() . Así que solo lo llamas cuando cambiaste algo al Observable y quieres que el resto de los Observers sepa.

  3. Notificar a todos los observadores que el Observable específico ha cambiado de estado. Esto se hace a través de notifyObservers() . Esto comprueba si el objeto realmente ha cambiado (es decir, se realizó una llamada a setChanged() ) antes de continuar con la notificación. Hay 2 versiones, una sin argumentos y otra con un argumento Object , en caso de que quiera pasar información adicional con la notificación. Internamente, lo que sucede es que simplemente recorre la lista de instancias de Observer y llama al método de update(Observable o, Object arg) para cada uno de ellos. Esto le dice al Observer que fue el Objeto Observable que cambió (podría estar observando más de uno), y el Object arg adicional para potencialmente llevar algo de información extra (pasado a través de notifyObservers() .


He escrito una breve descripción del patrón del observador aquí: http://www.devcodenote.com/2015/04/design-patterns-observer-pattern.html

Un fragmento de la publicación:

Patrón de observador: Establece esencialmente una relación uno a muchos entre los objetos y tiene un diseño débilmente acoplado entre los objetos interdependientes.

Definición de libro de texto: El patrón de observador define una dependencia de uno a muchos entre los objetos para que cuando un objeto cambie de estado, todos sus dependientes sean notificados y actualizados automáticamente.

Considere un servicio de notificación de alimentación, por ejemplo. Los modelos de suscripción son los mejores para comprender el patrón del observador.


Observer aka callback está registrada en Observable.

Se usa para informar, por ejemplo, sobre eventos que ocurrieron en algún momento. Se usa ampliamente en Swing, Ajax, GWT para despachar operaciones, por ejemplo, en eventos de IU (clics de botón, campos de texto cambiados, etc.).

En Swing encuentras métodos como addXXXListener (Listener l), en GWT tienes devoluciones de llamada (Async).

Como la lista de observadores es dinámica, los observadores pueden registrarse y anular el registro durante el tiempo de ejecución. También es una buena manera de desacoplar observable de los observadores, ya que se utilizan interfaces.


Si el entrevistador solicita implementar el patrón de diseño del observador sin utilizar las clases e interfaces de Observer, ¡puede usar el siguiente ejemplo simple!

MyObserver como interfaz de observador

interface MyObserver { void update(MyObservable o, Object arg); }

MyObservable como clase Observable

class MyObservable { ArrayList<MyObserver> myObserverList = new ArrayList<MyObserver>(); boolean changeFlag = false; public void notifyObservers(Object o) { if (hasChanged()) { for(MyObserver mo : myObserverList) { mo.update(this, o); } clearChanged(); } } public void addObserver(MyObserver o) { myObserverList.add(o); } public void setChanged() { changeFlag = true; } public boolean hasChanged() { return changeFlag; } protected void clearChanged() { changeFlag = false; } // ... }

¡Tu ejemplo con MyObserver y MyObservable!

class MessageBoard extends MyObservable { private String message; public String getMessage() { return message; } public void changeMessage(String message) { this.message = message; setChanged(); notifyObservers(message); } public static void main(String[] args) { MessageBoard board = new MessageBoard(); Student bob = new Student(); Student joe = new Student(); board.addObserver(bob); board.addObserver(joe); board.changeMessage("More Homework!"); } } class Student implements MyObserver { public void update(MyObservable o, Object arg) { System.out.println("Message board changed: " + arg); } }


Son parte del patrón de diseño del Observador . Por lo general, uno o más observadores se informan sobre los cambios en un observable . Es una notificación que "algo" sucedió, donde usted, como programador, puede definir qué significa "algo".

Cuando usa este patrón, desacopla las dos entidades una de otra: los observadores se vuelven conectables.


Tienes un ejemplo concreto de un Student y un MessageBoard. El Estudiante se registra al agregarse a la lista de Observadores que desean recibir notificaciones cuando se publica un Mensaje nuevo en el Tablero de Mensajes. Cuando se agrega un mensaje al MessageBoard, itera sobre su lista de observadores y les notifica que el evento ocurrió.

Piensa en Twitter. Cuando dices que quieres seguir a alguien, Twitter te agrega a su lista de seguidores. Cuando enviaron un nuevo tweet, lo ves en tu entrada. En ese caso, su cuenta de Twitter es el Observador y la persona que está siguiendo es el Observable.

La analogía podría no ser perfecta, porque es más probable que Twitter sea un Mediador. Pero ilustra el punto.


"Traté de averiguar, por qué exactamente necesitamos Observer y Observable"

Como las respuestas anteriores ya indicadas, proporcionan medios para suscribir un observador y recibir notificaciones automáticas de un observable.

Una aplicación de ejemplo donde esto puede ser útil es en el enlace de datos , digamos que tiene alguna UI que edita algunos datos, y desea que la IU reaccione cuando los datos se actualicen, puede hacer que sus datos sean observables y suscribir sus componentes de UI a los datos

Knockout.js es un MVVM javascript framework que tiene un excelente tutorial para comenzar, para ver más observables en acción. Realmente recomiendo seguir el tutorial. http://learn.knockoutjs.com/

También encontré este artículo en la página de inicio de Visual Studio 2008 ( El patrón Observer es la base del desarrollo de Model View Controller (MVC) ) http://visualstudiomagazine.com/articles/2013/08/14/the-observer-pattern-in-net.aspx


Definición

El patrón de observador se usa cuando hay una relación de uno a muchos entre objetos, como si un objeto se modifica, sus objetos dependientes se notificarán automáticamente y los cambios correspondientes se realizarán a todos los objetos dependientes.

Ejemplos

  1. Digamos, su dirección permanente ha sido modificada, entonces debe notificar a la autoridad de pasaportes y la autoridad de la tarjeta pan. Por lo tanto, aquí la autoridad de pasaporte y la autoridad de la tarjeta pan son observadores y usted es un sujeto.

  2. En Facebook también, si se suscribe a alguien, cada vez que se produzcan nuevas actualizaciones, se lo notificará.

Cuándo usarlo:

1. When one object changes its state,then all other dependents object must automatically change their state to maintain consistency 2. When subject doesn''t know about number of observers it has. 3. When an object should be able to notify other objects without knowing who objects are.

Paso 1

Crear clase de sujeto.

Subject.java

import java.util.ArrayList; import java.util.List; public class Subject { private List<Observer> observers = new ArrayList<Observer>(); private int state; public int getState() { return state; } public void setState(int state) { this.state = state; notifyAllObservers(); } public void attach(Observer observer){ observers.add(observer); } public void notifyAllObservers(){ for (Observer observer : observers) { observer.update(); } }

}

Paso 2

Crear clase de observador.

Observer.java

public abstract class Observer { protected Subject subject; public abstract void update(); }

Paso 3

Crear clases de observadores concretas

BinaryObserver.java

public class BinaryObserver extends Observer{ public BinaryObserver(Subject subject){ this.subject = subject; this.subject.attach(this); } @Override public void update() { System.out.println( "Binary String: " + Integer.toBinaryString( subject.getState() ) ); }

}

OctalObserver.java

public class OctalObserver extends Observer{ public OctalObserver(Subject subject){ this.subject = subject; this.subject.attach(this); } @Override public void update() { System.out.println( "Octal String: " + Integer.toOctalString( subject.getState() ) ); }

}

HexaObserver.java

public class HexaObserver extends Observer{ public HexaObserver(Subject subject){ this.subject = subject; this.subject.attach(this); } @Override public void update() { System.out.println( "Hex String: " + Integer.toHexString( subject.getState() ).toUpperCase() ); }

}

Etapa 4

Usa sujetos y objetos observadores concretos.

ObserverPatternDemo.java

public class ObserverPatternDemo { public static void main(String[] args) { Subject subject = new Subject(); new HexaObserver(subject); new OctalObserver(subject); new BinaryObserver(subject); System.out.println("First state change: 15"); subject.setState(15); System.out.println("Second state change: 10"); subject.setState(10); }

}

Paso 5

Verifica la salida.

Primer cambio de estado: 15

Hex String: F

Cadena octal: 17

Cadena binaria: 1111

Segundo cambio de estado: 10

Hex String: A

Cadena octal: 12

Cadena binaria: 1010