Quando dovremmo usare Observer e Observable?


200

Un intervistatore mi ha chiesto:

Cosa è Observere Observablequando dovremmo li usiamo?

Non ero a conoscenza di questi termini, quindi quando sono tornato a casa e ho iniziato a cercare su Google Observere Observableho trovato alcuni punti da diverse risorse:

1) Observableè una classe ed Observerè un'interfaccia.

2) La Observableclasse mantiene un elenco di Observers.

3) Quando un Observableoggetto viene aggiornato, invoca il update()metodo di ciascuna delle sue Observers per notificarlo, viene modificato.

Ho trovato questo esempio:

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!");
    }
}

Ma non capisco perché ne abbiamo bisogno Observere Observable? A cosa servono i metodi setChanged()e notifyObservers(message)?


Il link non funziona. @Androider Puoi fornire un link aggiornato?
prateek,

Se stai usando Java 6 o versioni successive, prova questo dzone.com/articles/java-ee6-events-lightweight
Ramiz Uddin

1
Consiglio vivamente di leggere questo libro per capire bene i modelli di design. Si presenta sciocco, ma è un eccellente strumento di apprendimento.
countofmontecristo,

1
Tutti lo notate per favore; Observer / Observable è deprecato in Java 9. Alternative: stackoverflow.com/questions/46380073/...
eren130

Risposte:


265

Hai un esempio concreto di uno studente e un MessageBoard. Lo studente si registra aggiungendosi all'elenco degli osservatori che desiderano essere avvisati quando un nuovo messaggio viene pubblicato nella MessageBoard. Quando un messaggio viene aggiunto a MessageBoard, scorre sul suo elenco di osservatori e notifica loro che si è verificato l'evento.

Pensa a Twitter. Quando dici di voler seguire qualcuno, Twitter ti aggiunge al suo elenco di follower. Quando hanno inviato un nuovo tweet, lo vedi nei tuoi input. In tal caso, il tuo account Twitter è l'Osservatore e la persona che stai seguendo è l'Osservabile.

L'analogia potrebbe non essere perfetta, perché Twitter ha più probabilità di essere un mediatore. Ma illustra il punto.


57

In termini molto semplici (perché le altre risposte ti rimandano comunque a tutti i modelli di design ufficiali, quindi guardali per ulteriori dettagli):

Se vuoi avere una classe monitorata da altre classi nell'ecosistema del tuo programma, dici che vuoi che la classe sia osservabile. Vale a dire che potrebbero esserci dei cambiamenti nel suo stato che vorresti trasmettere al resto del programma.

Ora, per fare questo dobbiamo chiamare un qualche tipo di metodo. Non vogliamo che la classe Observable sia strettamente accoppiata con le classi che sono interessate ad osservarla. Non importa chi è, purché soddisfi determinati criteri. (Immagina che sia una stazione radio, non gli importa chi ascolta finché hanno una radio FM sintonizzata sulla loro frequenza). A tal fine, utilizziamo un'interfaccia, denominata Observer.

Pertanto, la classe Observable avrà un elenco di osservatori (ovvero istanze che implementano i metodi di interfaccia Observer che potresti avere). Ogni volta che vuole trasmettere qualcosa, chiama semplicemente il metodo su tutti gli osservatori, uno dopo l'altro.

L'ultima cosa per chiudere il puzzle è come farà la classe osservabile a sapere chi è interessato? Quindi la classe Osservabile deve offrire un meccanismo per consentire agli Osservatori di registrare il proprio interesse. Un metodo comeaddObserver(Observer o) internamente aggiunge l'Observer all'elenco degli osservatori, in modo che quando accade qualcosa di importante, scorre attraverso l'elenco e chiama il rispettivo metodo di notifica dell'interfaccia Observer di ciascuna istanza nell'elenco.

Potrebbe essere che nell'intervista non ti abbiano chiesto esplicitamente del java.util.Observerejava.util.Observable concetto generico ma. Il concetto è un modello di progettazione, a cui Java fornisce supporto direttamente per consentirti di implementarlo rapidamente quando ne hai bisogno. Quindi suggerirei di capire il concetto piuttosto che i metodi / le classi attuali (che puoi cercare quando ne hai bisogno).

AGGIORNARE

In risposta al tuo commento, la java.util.Observableclasse attuale offre i seguenti servizi:

  1. Mantenimento di un elenco di java.util.Observeristanze. Le nuove istanze interessate a ricevere notifiche possono essere aggiunte addObserver(Observer o)e rimossedeleteObserver(Observer o) .

  2. Mantenimento di uno stato interno, specificando se l'oggetto è cambiato dall'ultima notifica agli osservatori. Ciò è utile perché separa la parte in cui si dice che Observableè cambiata, dalla parte in cui si notificano le modifiche. (Ad esempio, è utile se si verificano più modifiche e si desidera notificare solo alla fine del processo anziché a ogni piccolo passaggio). Questo è fatto attraverso setChanged(). Quindi lo chiami quando hai cambiato qualcosa in Observablee vuoi il resto delObservers alla fine lo sappia.

  3. Notifica a tutti gli osservatori che lo specifico Observableha cambiato stato. Questo è fatto attraverso notifyObservers(). Verifica se l'oggetto è stato effettivamente modificato (ovvero è setChanged()stata effettuata una chiamata a ) prima di procedere con la notifica. Esistono 2 versioni, una senza argomenti e una con un Objectargomento, nel caso in cui si desideri passare alcune informazioni aggiuntive con la notifica. Internamente ciò che accade è che scorre semplicemente attraverso l'elenco delle Observeristanze e chiama il update(Observable o, Object arg)metodo per ognuna di esse. Questo dice Observerquale era l'oggetto osservabile che è cambiato (potresti osservarne più di uno) e il supplemento Object argper potenzialmente trasportare alcune informazioni extra (passate attraverso notifyObservers().


37

Definizione

Il modello di osservatore viene utilizzato quando esiste una o più relazioni tra oggetti, ad esempio se un oggetto viene modificato, i suoi oggetti dipendenti devono essere notificati automaticamente e le modifiche corrispondenti vengono apportate a tutti gli oggetti dipendenti.

Esempi

  1. Supponiamo che il tuo indirizzo permanente sia cambiato, quindi devi avvisare l'autorità del passaporto e l'autorità della carta di credito. Quindi qui l'autorità del passaporto e l'autorità della carta pan sono osservatori e tu sei un soggetto.

  2. Anche su Facebook, se ti iscrivi a qualcuno, ogni volta che si verificano nuovi aggiornamenti, riceverai una notifica.

Quando usarlo:

  1. Quando un oggetto cambia il suo stato, tutti gli altri oggetti dipendenti devono cambiare automaticamente il loro stato per mantenere la coerenza

  2. Quando il soggetto non è a conoscenza del numero di osservatori che ha.

  3. Quando un oggetto dovrebbe essere in grado di notificare altri oggetti senza sapere chi sono gli oggetti.

Passo 1

Crea classe soggetto.

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

}

Passo 2

Crea classe Observer.

Observer.java

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

Passaggio 3

Crea classi di osservatori concreti

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

}

Passaggio 4

Usa oggetti soggetto e osservatore concreto.

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

}

Passaggio 5

Verifica l'output.

Primo cambio di stato: 15

Stringa esadecimale: F

Corda ottale: 17

Stringa binaria: 1111

Secondo cambio di stato: 10

Stringa esadecimale: A

Corda ottale: 12

Stringa binaria: 1010


ben spiegato :)
roottraveller

3
Penso che "Definizione" sia un refuso. Spero sia un errore di battitura.
John John il

10

Fanno parte del modello di progettazione di Observer . Di solito uno o più obervers vengono informati dei cambiamenti in un osservabile . È una notifica che "qualcosa" è accaduto, in cui tu come programmatore puoi definire cosa significa "qualcosa".

Quando si utilizza questo modello, si separano le due entità l'una dall'altra - gli osservatori diventano collegabili.


apprezzerò, se aggiungerai la spiegazione board.changeMessage("More Homework!");nella tua risposta, intendo cosa succede quando changeMessage("More Homework!");invocato.
Ravi,

9

Observer aka callback è registrato su Observable.

Viene utilizzato per informare, ad esempio, di eventi accaduti in un determinato momento. È ampiamente utilizzato in Swing, Ajax, GWT per operazioni di dispacciamento di eventi UI (clic sui pulsanti, campi di testo modificati ecc.).

In Swing trovi metodi come addXXXListener (Listener l), in GWT hai callback (Async).

Poiché l'elenco degli osservatori è dinamico, gli osservatori possono registrarsi e annullare la registrazione durante il runtime. È anche un buon modo per disaccoppiare osservabili dagli osservatori, poiché vengono utilizzate le interfacce.


9

Se l'intervistatore chiede di implementare il modello di progettazione di Observer senza utilizzare le classi e le interfacce di Observer, è possibile utilizzare il seguente esempio semplice!

MyObserver come interfaccia di osservazione

interface MyObserver {

    void update(MyObservable o, Object arg);
}

MyObservable come classe osservabile

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

    // ...
}

Il tuo esempio con MyObserver e 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);
  }

}

5

"Ho cercato di capire, perché esattamente abbiamo bisogno di osservatori e osservabili"

Come già affermato in precedenza, forniscono mezzi per iscrivere un osservatore a ricevere notifiche automatiche di un osservabile.

Un'applicazione di esempio in cui ciò può essere utile è nel data binding , supponiamo che tu abbia un'interfaccia utente che modifica alcuni dati e desideri che l'interfaccia utente reagisca quando i dati vengono aggiornati, puoi renderli osservabili e iscrivere i componenti dell'interfaccia utente a i dati

Knockout.js è un framework javascript MVVM che ha un ottimo tutorial per iniziare, per vedere più osservabili in azione consiglio vivamente di passare attraverso il tutorial. http://learn.knockoutjs.com/

Ho anche trovato questo articolo nella pagina iniziale di Visual Studio 2008 ( The Observer Pattern è il fondamento dello sviluppo di Model View Controller (MVC) ) http://visualstudiomagazine.com/articles/2013/08/14/the-observer-pattern-in -net.aspx


3

Ho scritto una breve descrizione del modello di osservatore qui: http://www.devcodenote.com/2015/04/design-patterns-observer-pattern.html

Uno snippet dal post:

Modello di osservatore: fondamentalmente stabilisce una relazione uno-a-molti tra oggetti e ha un disegno liberamente accoppiato tra oggetti interdipendenti.

Definizione del libro di testo: il modello di osservatore definisce una dipendenza uno-a-molti tra gli oggetti in modo che quando un oggetto cambia stato, tutti i suoi dipendenti vengono notificati e aggiornati automaticamente.

Ad esempio, considera un servizio di notifica feed. I modelli di abbonamento sono i migliori per comprendere il modello di osservatore.


0

Il modello di osservatore viene utilizzato quando esiste una relazione uno-a-molti tra oggetti, ad esempio se un oggetto viene modificato, i suoi oggetti dipendenti devono essere notificati automaticamente.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.