risposta-alla-domanda-sullo-sviluppo-web-bd.com

Quando dovremmo usare Observer and Observable?

Un intervistatore mi ha chiesto:

Cosa sono Observer e Observable e quando dovremmo usarli?

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

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

2) La classe Observable mantiene un elenco di Observers.

3) Quando un oggetto Observable viene aggiornato, richiama il metodo update() di ciascuno dei suoi Observers per notificare che è cambiato.

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é abbiamo bisogno di Observer e Observable? Per quali sono i metodi setChanged() e notifyObservers(message)?

181
Ravi

Hai un esempio concreto di uno Studente e una MessageBoard. Lo studente si registra aggiungendosi alla lista di osservatori che vogliono essere avvisati quando un nuovo messaggio viene inviato alla MessageBoard. Quando un messaggio viene aggiunto alla MessageBoard, itera sopra il suo elenco di Observers e notifica loro che l'evento si è verificato.

Pensa a Twitter. Quando dici di voler seguire qualcuno, Twitter ti aggiunge alla lista dei follower. Quando hanno inviato un nuovo tweet, lo vedi nel tuo contributo. In tal caso, il tuo account Twitter è l'Observer e la persona che stai seguendo è Observable.

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

243
duffymo

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

Se vuoi avere una classe che è monitorata da altre classi nell'ecosistema del tuo programma, dici che vuoi che la classe sia osservabile. Cioè 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 gli importa chi è finché soddisfa determinati criteri. (Immagina che si tratti di una stazione radio, non gli importa chi sta ascoltando a patto che abbiano una radio FM sintonizzata sulla loro frequenza). Per riuscirci utilizziamo un'interfaccia, indicata come Observer. 

Pertanto, la classe Observable avrà una lista di Observers (cioè istanze che implementano i metodi di interfaccia di 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 Observable a sapere chi è interessato? Quindi la classe Observable deve offrire qualche meccanismo per permettere agli osservatori di registrare il loro interesse. Un metodo come addObserver(Observer o) aggiunge internamente l'Observer alla lista di osservatori, in modo che quando accade qualcosa di importante, scorre attraverso l'elenco e chiama il rispettivo metodo di notifica dell'interfaccia Observer di ogni istanza nell'elenco.

Potrebbe essere che nel colloquio non ti abbiano chiesto esplicitamente il Java.util.Observer e Java.util.Observable ma il concetto generico. Il concetto è un modello di progettazione, che Java fornisce per supportare direttamente fuori dalla scatola per aiutarti a implementarlo rapidamente quando ne hai bisogno. Quindi ti suggerisco di capire il concetto piuttosto che i metodi/le classi effettive (che puoi cercare quando ne hai bisogno).

AGGIORNARE

In risposta al tuo commento, l'attuale Java.util.Observable class offre le seguenti funzionalità:

  1. Mantenimento di un elenco di istanze Java.util.Observer. Le nuove istanze interessate ad essere notificate possono essere aggiunte tramite addObserver(Observer o) e rimosse tramite deleteObserver(Observer o).

  2. Mantenimento di uno stato interno, che specifica se l'oggetto è cambiato dall'ultima notifica agli osservatori. Questo è utile perché separa la parte in cui dici che Observable è cambiato, dalla parte in cui si notificano le modifiche. (Ad esempio, è utile se si verificano più cambiamenti e si desidera solo notificare alla fine del processo piuttosto che ad ogni piccolo passo). Questo è fatto attraverso setChanged(). Quindi lo chiami quando hai cambiato qualcosa in Observable e vuoi che il resto del Observers lo sappia.

  3. Notifica a tutti gli osservatori che lo specifico Observable ha cambiato stato. Questo è fatto attraverso notifyObservers(). Questo controlla se l'oggetto è effettivamente cambiato (cioè è stata effettuata una chiamata a setChanged()) prima di procedere con la notifica. Ci sono 2 versioni, una senza argomenti e una con un argomento Object, nel caso in cui si vogliano passare alcune informazioni aggiuntive con la notifica. Internamente ciò che accade è che itera semplicemente attraverso l'elenco delle istanze Observer e chiama il metodo update(Observable o, Object arg) per ognuno di essi. Questo dice al Observer che era l'oggetto Observable che è cambiato (potreste stare osservando più di uno), e il Object arg extra per portare potenzialmente alcune informazioni extra (passate attraverso notifyObservers().

53
jbx

Definizione

Il pattern Observer viene usato quando c'è una relazione uno a molti tra oggetti come se un oggetto è modificato, i suoi oggetti dipendenti devono essere notificati automaticamente e le modifiche corrispondenti vengono fatte a tutti gli oggetti dipendenti.

Esempi

  1. Diciamo che il tuo indirizzo permanente è cambiato, quindi devi notificare l'autorità del passaporto e l'autorità della scheda pan. Quindi qui l'autorità del passaporto e l'autorità della scheda pan sono osservatori e tu sei un soggetto.

  2. Anche su Facebook, se ti iscrivi a qualcuno allora ogni volta che si verificano nuovi aggiornamenti ti verrà notificato.

Quando 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.

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 una classe Observer.

Observer.Java

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

Passaggio 3

Creare 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 Oggetto osservatore e 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

Stringa ottale: 17

Stringa binaria: 1111

Secondo cambio di stato: 10

Stringa esadecimale: A

Stringa ottale: 12

Stringa binaria: 1010

32
Mubarak

Sono parti del modello di progettazione Observer . Di solito uno o più server vengono informati sui cambiamenti in uno osservabile. È una notazione che "qualcosa" è accaduto, in cui voi come programmatori potete definire cosa significa "qualcosa".

Quando si utilizza questo modello, si disaccoppiano entrambe le entità l'una dall'altra: gli osservatori diventano inseribili.

10
Andy

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

MyObserver come interfaccia di osservazione

interface MyObserver {

    void update(MyObservable o, Object arg);
}

MyObservable as Observable class

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

}
9
Habeeb Perwad

Osservatore a.k.a La richiamata è registrata su Osservabile.

È usato per informare ad es. sugli eventi accaduti in un determinato momento. È ampiamente utilizzato in Swing, Ajax, GWT per le operazioni di dispacciamento ad es. Eventi dell'interfaccia utente (clic sui pulsanti, campi di testo modificati, ecc.).

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

Poiché la lista degli osservatori è dinamica, gli osservatori possono registrarsi e annullare la registrazione durante il runtime. È anche un buon modo per separare l'osservatore dagli osservatori, in quanto vengono utilizzate le interfacce.

9
Pawel Solarski

"Ho cercato di capire perché esattamente abbiamo bisogno di Observer and Observable"

Come già affermato nelle risposte precedenti, forniscono i mezzi per sottoscrivere un osservatore per ricevere notifiche automatiche di un osservabile. 

Un'applicazione di esempio in cui ciò può essere utile è in data binding, supponiamo che tu abbia un'interfaccia utente che modifica alcuni dati e vuoi che l'IU reagisca quando i dati vengono aggiornati, puoi rendere i tuoi dati osservabili e iscriverti le tue componenti dell'interfaccia utente ai 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 Model View Controller (MVC)) http://visualstudiomagazine.com/articles/2013/08/ 14/the-observer-pattern-in-net.aspx

5
Eduardo Wada

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

Un frammento del post:

Modello di osservatore: Stabilisce essenzialmente una relazione uno-a-molti tra oggetti e ha un design 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 avvisati e aggiornati automaticamente.

Prendi in considerazione un servizio di notifica dei feed, ad esempio. I modelli di abbonamento sono i migliori per comprendere il modello di osservatore.

3
Abhishek Jain

Il pattern Observer viene usato quando c'è una relazione uno-a-molti tra oggetti come se un oggetto è modificato, i suoi oggetti dipendenti devono essere notificati automaticamente.

0
Swapnil Sharma

Dal momento che Java9, entrambe le interfacce sono deprecate, il che significa che non dovresti più usarle. Vedi Observer è obsoleto in Java 9. Cosa dovremmo usare al posto di esso?

Tuttavia, potresti comunque ricevere domande sull'intervista su di loro ...

0
tkruse