¿Cuándo debemos usar Observador y Observable?

200

Un entrevistador me preguntó:

¿Qué es Observery Observablecuándo debemos usarlos?

No estaba al tanto de estas condiciones, así que cuando llegué de vuelta a casa y empecé a buscar en Google sobre Observery Observable, he encontrado algunos puntos de diferentes recursos:

1) Observablees una clase yObserver es una interfaz.

2) La Observableclase mantiene una lista deObserver s.

3) Cuando Observablese actualiza un objeto, invoca el update()método de cada uno de sus Observercorreos electrónicos para notificar que se modifica.

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 Observery Observable? ¿Cuáles son las setChanged()y notifyObservers(message)los métodos para?

Ravi
fuente
El enlace no funciona. @Androider ¿Puede proporcionar un enlace actualizado?
prateek
Si está utilizando Java 6 o superior, pruebe este dzone.com/articles/java-ee6-events-lightweight
Ramiz Uddin el
1
Recomiendo encarecidamente leer este libro para comprender mejor los patrones de diseño. Parece tonto, pero es una excelente herramienta de aprendizaje.
countofmontecristo
1
Todos tengan en cuenta eso; Observer / Observable está en desuso en Java 9. Alternativas: stackoverflow.com/questions/46380073/…
eren130

Respuestas:

265

Tiene un ejemplo concreto de un estudiante y un tablero de mensajes. El Estudiante se registra agregándose a la lista de Observadores que desean ser notificados cuando se publica un nuevo Mensaje en el Tablero de mensajes. Cuando se agrega un mensaje al tablero de mensajes, itera sobre su lista de observadores y les notifica que ocurrió el evento.

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.

duffymo
fuente
57

En términos muy simples (porque las otras respuestas lo están refiriendo 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 que es monitoreada por otras clases en el ecosistema de su programa, usted dice que desea que la clase sea observable. Es decir, puede haber algunos cambios en su estado que desearía 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 sea, siempre y cuando cumpla con ciertos criterios. (Imagine que es una estación de radio, no le importa quién está escuchando mientras tenga una radio FM sintonizada en su frecuencia). Para lograrlo, utilizamos una interfaz, denominada Observador.

Por lo tanto, la clase Observable tendrá una lista de observadores (es decir, instancias que implementarán los métodos de interfaz de observador que pueda tener). Cada vez que quiere transmitir algo, simplemente llama al método en todos los observadores, uno tras otro.

Lo último que cierra el rompecabezas es cómo sabrá la clase Observable quién está interesado. Por lo tanto, la clase Observable debe ofrecer algún mecanismo que permita a los Observadores registrar su interés. Un método comoaddObserver(Observer o) interno agrega al Observador a la lista de observadores, de modo que cuando sucede algo importante, recorre la lista y llama al método de notificación respectivo de la interfaz del Observador de cada instancia en la lista.

Puede ser que en la entrevista no le hayan preguntado explícitamente sobre el java.util.Observeryjava.util.Observable concepto genérico sino sobre él. El concepto es un patrón de diseño, que Java proporciona soporte directamente fuera de la caja para ayudarlo a implementarlo rápidamente cuando lo necesite. Por lo tanto, sugeriría 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 java.util.Observableclase real ofrece las siguientes instalaciones:

  1. Mantener una lista de java.util.Observerinstancias. Se pueden agregar addObserver(Observer o)y eliminar nuevas instancias interesadas en recibir notificaciones 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 Observableha cambiado, de 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 en cada pequeño paso). Esto se hace a través de setChanged(). Así que simplemente lo llamas cuando cambiaste algo Observabley quieres que el resto lo Observerssepa.

  3. Notificar a todos los observadores que lo específico Observableha cambiado de estado. Esto se hace a través de notifyObservers(). Esto verifica 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 Objectargumento, en caso de que desee pasar información adicional con la notificación. Internamente, lo que sucede es que simplemente recorre la lista de Observerinstancias y llama al update(Observable o, Object arg)método para cada una de ellas. Esto indica Observercuál fue el objeto Observable que cambió (podría estar observando más de uno) y el extra Object argpara llevar potencialmente información adicional (transmitida) notifyObservers().

jbx
fuente
37

Definición

El patrón de observador se utiliza cuando hay una relación de uno a muchos entre los objetos, por ejemplo, si se modifica un objeto, sus objetos dependientes deben ser notificados automáticamente y se realizan los cambios correspondientes a todos los objetos dependientes.

Ejemplos

  1. Digamos que su dirección permanente se cambia, entonces debe notificar a la autoridad del pasaporte y la autoridad de la tarjeta panorámica. Así que aquí la autoridad del pasaporte y la autoridad de la tarjeta panorámica son observadores y Tú eres un sujeto.

  2. También en Facebook, si se suscribe a alguien, cada vez que ocurran nuevas actualizaciones, se le notificará.

Cuando usarlo:

  1. Cuando un objeto cambia su estado, todos los demás objetos dependientes deben cambiar automáticamente su estado para mantener la coherencia.

  2. Cuando el sujeto no sabe sobre el número de observadores que tiene.

  3. Cuando un objeto debe poder notificar a otros objetos sin saber quiénes son.

Paso 1

Crear clase de sujeto.

Sujeto.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 concretos

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

}

Paso 4

Usar sujetos y objetos de observación 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

Verifique la salida.

Primer cambio de estado: 15

Cadena hexagonal: F

Cadena octal: 17

Cadena binaria: 1111

Segundo cambio de estado: 10

Cadena hexagonal: A

Cadena octal: 12

Cadena binaria: 1010

Mubarak
fuente
muy bien explicado :)
roottraveller
3
Creo que "Definición" es un error tipográfico. Espero que sea un error tipográfico.
JohnJohn
10

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

Cuando usa este patrón, desacopla las dos entidades entre sí, los observadores se vuelven conectables.

Andy
fuente
Le agradeceré que, si agrega la explicación board.changeMessage("More Homework!");en su respuesta, me refiero a lo que sucede cuando se changeMessage("More Homework!");invoca.
Ravi
9

Observer aka callback está registrado en Observable.

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

En Swing encontrará métodos como addXXXListener (Listener l), en GWT tiene devoluciones de llamada (Async).

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

Pawel Solarski
fuente
9

Si el entrevistador solicita implementar el patrón de diseño de Observer sin usar 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;
    }

    // ...
}

¡Su 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 {

  @Override
  public void update(MyObservable o, Object arg) {
    System.out.println("Message board changed: " + arg);
  }

}
Habeeb Perwad
fuente
5

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

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

Un ejemplo de aplicación donde esto puede ser útil es en el enlace de datos , supongamos que tiene alguna interfaz de usuario que edita algunos datos y desea que la interfaz de usuario reaccione cuando se actualizan los datos, puede hacer que sus datos sean observables y suscribir sus componentes de la interfaz de usuario a los datos

Knockout.js es un marco de JavaScript MVVM que tiene un excelente tutorial de inicio, para ver más observables en acción, realmente recomiendo pasar por el tutorial. http://learn.knockoutjs.com/

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

Eduardo Wada
fuente
3

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

Un fragmento de la publicación:

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

Definición del libro de texto: el patrón de observador define una dependencia de uno a muchos entre los objetos, de modo que cuando un objeto cambia de estado, todos sus dependientes son notificados y actualizados automáticamente.

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

Abhishek Jain
fuente
0

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

Swapnil Sharma
fuente