it-swarm.com.de

Wann sollten wir Observer und Observable verwenden?

Ein Interviewer fragte mich:

Was ist Observer und Observable und wann sollten wir sie verwenden?

Ich war mir dieser Bedingungen nicht bewusst. Als ich nach Hause kam und Googling über Observer und Observable begann, fand ich einige Punkte aus verschiedenen Quellen:

1) Observable ist eine Klasse und Observer ist eine Schnittstelle.

2) Die Observable-Klasse führt eine Liste von Observers.

3) Wenn ein Observable-Objekt aktualisiert wird, ruft es die update()-Methode jeder seiner Observers auf, um dies zu melden, es wird geändert.

Ich habe dieses Beispiel gefunden:

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

Aber ich verstehe nicht, warum wir Observer und Observable brauchen? Was sind die setChanged()- und notifyObservers(message)-Methoden?

181
Ravi

Sie haben ein konkretes Beispiel für einen Studenten und ein MessageBoard. Der Student registriert sich, indem er sich der Liste der Beobachter hinzufügt, die benachrichtigt werden möchten, wenn eine neue Nachricht an das MessageBoard gesendet wird. Wenn eine Nachricht zum MessageBoard hinzugefügt wird, durchläuft es die Liste der Beobachter und benachrichtigt sie, dass das Ereignis aufgetreten ist.

Denken Sie an Twitter. Wenn Sie sagen, dass Sie jemandem folgen möchten, fügt Twitter Sie Ihrer Follower-Liste hinzu. Wenn sie einen neuen Tweet gesendet haben, sehen Sie ihn in Ihrer Eingabe. In diesem Fall ist Ihr Twitter-Konto der Observer und die Person, der Sie folgen, der Observable.

Die Analogie ist möglicherweise nicht perfekt, da Twitter eher ein Mediator ist. Aber es veranschaulicht den Punkt.

243
duffymo

In sehr einfachen Worten (weil die anderen Antworten Sie ohnehin auf alle offiziellen Entwurfsmuster verweisen, schauen Sie sich diese für weitere Details an):

Wenn Sie eine Klasse haben möchten, die von anderen Klassen im Ökosystem Ihres Programms überwacht wird, sagen Sie, dass die Klasse beobachtbar sein soll. D.h. Möglicherweise gibt es einige Statusänderungen, die Sie an den Rest des Programms senden möchten.

Um dies zu tun, müssen wir eine Methode aufrufen. Wir möchten nicht, dass die Klasse Observable eng mit den Klassen verbunden ist, die daran interessiert sind, sie zu beobachten. Es ist egal, wer es ist, solange es bestimmte Kriterien erfüllt. (Stellen Sie sich vor, es handelt sich um einen Radiosender, es ist egal, wer hört, solange ein UKW-Radio auf seine Frequenz eingestellt ist). Um dies zu erreichen, verwenden wir eine als Observer bezeichnete Schnittstelle. 

Daher verfügt die Observable-Klasse über eine Liste von Observern (d. H. Instanzen, die möglicherweise die Observer-Schnittstellenmethoden implementieren). Wann immer etwas gesendet werden soll, ruft es die Methode bei allen Beobachtern nacheinander auf.

Das letzte, was das Puzzle abschließen kann, ist, wie die Observable-Klasse wissen kann, wer interessiert ist. Die Observable-Klasse muss also einen Mechanismus bieten, mit dem Beobachter ihr Interesse registrieren können. Eine Methode wie addObserver(Observer o) fügt den Observer intern der Liste der Beobachter hinzu. Wenn etwas Wichtiges passiert, durchläuft es die Liste und ruft die jeweilige Benachrichtigungsmethode der Observer-Schnittstelle jeder Instanz in der Liste auf.

Es könnte sein, dass Sie im Interview nicht explizit nach Java.util.Observer und Java.util.Observable gefragt wurden, sondern nach dem generischen Konzept. Das Konzept ist ein Entwurfsmuster, für das Java Support direkt nach dem Auspacken bietet, damit Sie es schnell implementieren können, wenn Sie es benötigen. Ich würde also vorschlagen, dass Sie das Konzept verstehen und nicht die tatsächlichen Methoden/Klassen (die Sie nachschlagen können, wenn Sie sie benötigen).

UPDATE

Als Antwort auf Ihren Kommentar bietet die tatsächliche Java.util.Observable class die folgenden Möglichkeiten:

  1. Eine Liste von Java.util.Observer-Instanzen verwalten. Neue Instanzen, die an einer Benachrichtigung interessiert sind, können über addObserver(Observer o) hinzugefügt und über deleteObserver(Observer o) entfernt werden.

  2. Beibehaltung eines internen Status, der angibt, ob sich das Objekt seit der letzten Benachrichtigung der Beobachter geändert hat. Dies ist nützlich, weil dadurch der Teil, in dem Sie sagen, dass Observable sich geändert hat, von dem Teil getrennt wird, in dem Sie die Änderungen benachrichtigen. (Zum Beispiel ist es nützlich, wenn mehrere Änderungen vorgenommen werden und Sie nur am Ende des Vorgangs und nicht bei jedem kleinen Schritt benachrichtigen möchten). Dies geschieht über setChanged(). Sie rufen es also einfach an, wenn Sie etwas an Observable geändert haben und der Rest der Observers schließlich davon erfahren soll.

  3. Alle Beobachter darüber informieren, dass der spezifische Observable-Status geändert wurde. Dies geschieht über notifyObservers(). Dies prüft, ob sich das Objekt tatsächlich geändert hat (d. H. Ein Aufruf von setChanged() wurde durchgeführt), bevor die Benachrichtigung fortgesetzt wird. Es gibt 2 Versionen, eine ohne Argumente und eine mit dem Argument Object, falls Sie zusätzliche Informationen mit der Benachrichtigung übergeben möchten. Was intern passiert, ist, dass es nur die Liste der Observer-Instanzen durchläuft und die update(Observable o, Object arg) -Methode für jede von ihnen aufruft. Dies teilt dem Observer mit, welches das Observable-Objekt war, das sich geändert hat (Sie könnten mehr als einen beobachten) und der zusätzliche Object arg, der möglicherweise zusätzliche Informationen enthält (durch notifyObservers() übergeben).

53
jbx

Definition

Observer Pattern wird verwendet, wenn zwischen Objekten eine zu viele Beziehung besteht, z. B. wenn ein Objekt geändert wird, die abhängigen Objekte automatisch benachrichtigt werden und entsprechende Änderungen an allen abhängigen Objekten vorgenommen werden.

Beispiele

  1. Nehmen wir an, Ihre ständige Adresse wird geändert. Dann müssen Sie die Passautorität und die Pan Card-Autorität benachrichtigen. Hier sind die Passautorität und die Pan Card-Behörde Beobachter und Sie sind ein Subjekt.

  2. Auf Facebook auch: Wenn Sie jemanden abonnieren, werden Sie bei neuen Updates benachrichtigt.

Wann verwenden:

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.

Schritt 1

Erstellen Sie die Subject-Klasse.

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

}

Schritt 2

Observer-Klasse erstellen.

Observer.Java

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

Schritt 3

Erstellen Sie konkrete Beobachterklassen

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

}

Schritt 4

Verwenden Sie Betreff und konkrete Beobachterobjekte.

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

}

Schritt 5

Überprüfen Sie die Ausgabe.

Erster Zustandswechsel: 15

Hex String: F

Oktalsaite: 17

Binäre Zeichenfolge: 1111

Zweite Zustandsänderung: 10

Hex String: A

Oktalsaite: 12

Binäre Zeichenfolge: 1010

32
Mubarak

Sie sind Teil des Observer-Entwurfsmusters . Normalerweise werden ein oder mehrere obervers über Änderungen in einem observable informiert. Es ist ein Hinweis, dass "etwas" passiert ist, wo Sie als Programmierer definieren können, was "etwas" bedeutet.

Wenn Sie dieses Muster verwenden, entkoppeln Sie die beiden Entitäten voneinander - die Beobachter werden steckbar.

10
Andy

Wenn der Interviewer bittet, das Observer-Entwurfsmuster zu implementieren, ohne Observer-Klassen und -Schnittstellen zu verwenden, können Sie das folgende einfache Beispiel verwenden! 

MyObserver als Observer-Schnittstelle

interface MyObserver {

    void update(MyObservable o, Object arg);
}

MyObservable als Observable-Klasse

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

    // ...
}

Ihr Beispiel mit MyObserver und 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

Observer a.k.a Callback ist bei Observable registriert.

Es wird zur Information verwendet, z. über Ereignisse, die zu einem bestimmten Zeitpunkt stattfanden. Es wird weit verbreitet in Swing, Ajax, GWT zum Versenden von Operationen an z. UI-Ereignisse (Schaltflächenklicks, geänderte Textfelder usw.).

In Swing finden Sie Methoden wie addXXXListener (Listener l), in GWT (Async) Callbacks.

Da die Liste der Beobachter dynamisch ist, können sich Beobachter zur Laufzeit registrieren und die Registrierung aufheben. Es ist auch eine gute Möglichkeit, beobachtbare Beobachtungen von Beobachtern abzukoppeln, da Schnittstellen verwendet werden.

9
Pawel Solarski

"Ich habe versucht herauszufinden, warum genau wir Observer und Observable brauchen"

Wie bereits erwähnt, bieten sie die Möglichkeit, einen Beobachter zu abonnieren, um automatische Benachrichtigungen eines Beobachtbaren zu erhalten. 

Eine Beispielanwendung, in der dies nützlich sein kann, ist data binding. Angenommen, Sie haben einige Benutzeroberflächen, die Daten bearbeiten, und Sie möchten, dass die Benutzeroberfläche auf die Aktualisierung der Daten reagiert. Sie können Ihre Daten beobachtbar machen und abonnieren Ihre UI-Komponenten zu den Daten

Knockout.js ist ein MVVM-Javascript-Framework, das ein großartiges Tutorial für Anfänger bietet. Um mehr Observables in Aktion zu sehen, empfehle ich wirklich, das Tutorial durchzugehen. http://learn.knockoutjs.com/

Ich habe diesen Artikel auch auf der Startseite von Visual Studio 2008 gefunden (Das Observer-Muster ist die Grundlage der Entwicklung von Model View Controller (MVC)) http://visualstudiomagazine.com/articles/2013/ 08/14/the-observer-pattern-in-net.aspx

5
Eduardo Wada

Ich habe hier eine kurze Beschreibung des Beobachtungsmusters geschrieben: http://www.devcodenote.com/2015/04/design-patterns-observer-pattern.html

Ein Ausschnitt aus der Post:

Beobachtermuster: Es stellt im Wesentlichen eine Eins-zu-Viele-Beziehung zwischen Objekten her und hat ein lose gekoppeltes Design zwischen voneinander abhängigen Objekten.

TextBook-Definition: Das Observer-Muster definiert eine Eins-zu-Viele-Abhängigkeit zwischen Objekten. Wenn ein Objekt seinen Status ändert, werden alle abhängigen Objekte automatisch benachrichtigt und aktualisiert.

Betrachten Sie beispielsweise einen Feed-Benachrichtigungsdienst. Abonnementmodelle sind das beste, um das Beobachtermuster zu verstehen.

3
Abhishek Jain

Observer Pattern wird verwendet, wenn zwischen Objekten eine Eins-zu-Viele-Beziehung besteht, z. B. wenn ein Objekt geändert wird, die abhängigen Objekte automatisch benachrichtigt werden.

0
Swapnil Sharma

Seit Java9 sind beide Schnittstellen veraltet, dh Sie sollten sie nicht mehr verwenden. Siehe Observer ist in Java 9 veraltet. Was sollten wir stattdessen verwenden?

Möglicherweise erhalten Sie jedoch noch Interviewfragen dazu ...

0
tkruse