Quand devrions-nous utiliser Observer et Observable?


200

Un intervieweur m'a demandé:

Qu'est-ce Observerque Observableet quand devons-nous les utiliser?

Je n'étais pas au courant de ces termes, donc quand je suis rentré chez moi et que j'ai commencé à googler Observeret Observable, j'ai trouvé quelques points de différentes ressources:

1) Observableest une classe et Observerest une interface.

2) La Observableclasse tient une liste de l' Observerart.

3) Lorsqu'un Observableobjet est mis à jour, il invoque la update()méthode de chacun de ses Observers pour le signaler, il est modifié.

J'ai trouvé cet exemple:

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

Mais je ne comprends pas pourquoi nous avons besoin de Observeret Observable? À quoi servent les méthodes setChanged()et notifyObservers(message)?


Le lien ne fonctionne pas. @Androider Pouvez-vous fournir un lien mis à jour?
prateek

Si vous utilisez Java 6 ou supérieur, essayez ceci dzone.com/articles/java-ee6-events-lightweight
Ramiz Uddin

1
Je suggère fortement de lire ce livre pour avoir une bonne compréhension des modèles de conception. Cela semble stupide, mais c'est un excellent outil d'apprentissage.
countofmontecristo

1
Tout le monde, veuillez le noter; Observer / Observable est déconseillé dans Java 9. Alternatives: stackoverflow.com/questions/46380073/…
eren130

Réponses:


265

Vous avez un exemple concret d'un étudiant et d'un MessageBoard. L'élève s'inscrit en s'ajoutant à la liste des observateurs qui souhaitent être avertis lorsqu'un nouveau message est publié sur le MessageBoard. Lorsqu'un message est ajouté au MessageBoard, il parcourt sa liste d'observateurs et les avertit que l'événement s'est produit.

Pensez Twitter. Lorsque vous dites que vous souhaitez suivre quelqu'un, Twitter vous ajoute à sa liste de suiveurs. Quand ils ont envoyé un nouveau tweet, vous le voyez dans votre entrée. Dans ce cas, votre compte Twitter est l'Observateur et la personne que vous suivez est l'Observable.

L'analogie n'est peut-être pas parfaite, car Twitter est plus susceptible d'être un médiateur. Mais cela illustre le point.


57

En termes très simples (parce que les autres réponses vous réfèrent à tous les modèles de conception officiels, alors regardez-les pour plus de détails):

Si vous voulez avoir une classe qui est surveillée par d'autres classes dans l'écosystème de votre programme, vous dites que vous voulez que la classe soit observable. C'est-à-dire qu'il pourrait y avoir quelques changements dans son état que vous voudriez diffuser au reste du programme.

Maintenant, pour ce faire, nous devons appeler une sorte de méthode. Nous ne voulons pas que la classe Observable soit étroitement couplée avec les classes qui souhaitent l'observer. Peu importe qui c'est tant qu'il remplit certains critères. (Imaginez que c'est une station de radio, peu importe qui écoute tant qu'ils ont une radio FM réglée sur leur fréquence). Pour ce faire, nous utilisons une interface, appelée Observateur.

Par conséquent, la classe Observable aura une liste d'observateurs (c'est-à-dire des instances mettant en œuvre les méthodes d'interface Observer que vous pourriez avoir). Chaque fois qu'il veut diffuser quelque chose, il appelle simplement la méthode sur tous les observateurs, l'un après l'autre.

La dernière chose pour fermer le puzzle est de savoir comment la classe Observable saura-t-elle qui est intéressée? La classe Observable doit donc offrir un mécanisme permettant aux observateurs d'enregistrer leur intérêt. Une méthode telle que addObserver(Observer o)l'ajout en interne de l'Observer à la liste des observateurs, de sorte que lorsque quelque chose d'important se produit, il parcourt la liste et appelle la méthode de notification respective de l'interface Observer de chaque instance de la liste.

Il se peut que dans l'interview, ils ne vous aient pas posé de questions explicites sur le java.util.Observeret java.util.Observablemais sur le concept générique. Le concept est un modèle de conception, que Java fournit pour prendre en charge directement hors de la boîte pour vous aider à l'implémenter rapidement lorsque vous en avez besoin. Je suggère donc que vous compreniez le concept plutôt que les méthodes / classes réelles (que vous pouvez rechercher lorsque vous en avez besoin).

METTRE À JOUR

En réponse à votre commentaire, la java.util.Observableclasse actuelle offre les installations suivantes:

  1. Maintenir une liste d' java.util.Observerinstances. De nouvelles instances intéressées à être notifiées peuvent être ajoutées addObserver(Observer o)et supprimées deleteObserver(Observer o).

  2. Maintien d'un état interne, spécifiant si l'objet a changé depuis la dernière notification aux observateurs. Ceci est utile car il sépare la partie où vous dites que le Observablea changé, de la partie où vous notifiez les modifications. (Par exemple, son utile si vous avez plusieurs changements en cours et que vous souhaitez uniquement notifier à la fin du processus plutôt qu'à chaque petite étape). Cela se fait à travers setChanged(). Donc, vous l'appelez simplement lorsque vous avez changé quelque chose en Observableet que vous voulez que le reste Observersen soit informé.

  3. Aviser tous les observateurs que le spécifique Observablea changé d'état. Cela se fait à travers notifyObservers(). Ceci vérifie si l'objet a réellement changé (c'est-à-dire qu'un appel a setChanged()été effectué) avant de procéder à la notification. Il existe 2 versions, une sans argument et une avec Objectargument, au cas où vous souhaiteriez transmettre des informations supplémentaires avec la notification. En interne, ce qui se passe, c'est qu'il parcourt simplement la liste des Observerinstances et appelle la update(Observable o, Object arg)méthode pour chacune d'elles. Cela indique Observerquel était l'objet observable qui a changé (vous pourriez en observer plus d'un), et le supplément Object argpour potentiellement transporter des informations supplémentaires (transmises) notifyObservers().


37

Définition

Le modèle d'observateur est utilisé lorsqu'il existe une relation un à plusieurs entre les objets, par exemple si un objet est modifié, ses objets dépendants doivent être notifiés automatiquement et les modifications correspondantes sont apportées à tous les objets dépendants.

Exemples

  1. Supposons que votre adresse permanente soit modifiée, vous devez en informer l'autorité des passeports et l'autorité de la carte pan. Donc, ici, l'autorité de passeport et l'autorité de carte panoramique sont des observateurs et vous êtes un sujet.

  2. Sur Facebook également, si vous vous abonnez à quelqu'un, chaque fois que de nouvelles mises à jour se produisent, vous en serez informé.

Quand l'utiliser:

  1. Lorsqu'un objet change son état, tous les autres objets dépendants doivent automatiquement changer leur état pour maintenir la cohérence

  2. Lorsque le sujet ne connaît pas le nombre d'observateurs dont il dispose.

  3. Quand un objet doit pouvoir notifier d'autres objets sans savoir qui sont les objets.

Étape 1

Créer une classe de sujet.

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

}

Étape 2

Créez une classe Observateur.

Observer.java

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

Étape 3

Créer des classes d'observateurs concrètes

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

}

Étape 4

Utilisez des objets sujets et des observateurs concrets.

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

}

Étape 5

Vérifiez la sortie.

Premier changement d'état: 15

Chaîne hexagonale: F

Chaîne octale: 17

Chaîne binaire: 1111

Deuxième changement d'état: 10

Chaîne hexagonale: A

Chaîne octale: 12

Chaîne binaire: 1010


joliment expliqué :)
roottraveller

3
Je pense que "Defination" est une faute de frappe. J'espère que c'est une faute de frappe.
JohnJohn

10

Ils font partie du modèle de conception Observer . Habituellement, un ou plusieurs observateurs sont informés des changements dans un observable . C'est une notification que "quelque chose" s'est produit, où vous en tant que programmeur pouvez définir ce que "quelque chose" signifie.

Lorsque vous utilisez ce modèle, vous dissociez les deux entités l'une de l'autre - les observateurs deviennent enfichables.


j'apprécierai, si vous ajoutez l'explication de board.changeMessage("More Homework!");dans votre réponse, je veux dire ce qui se passe lorsqu'il est changeMessage("More Homework!");invoqué.
Ravi

9

Observer aka callback est enregistré sur Observable.

Il est utilisé pour informer, par exemple, sur les événements qui se sont produits à un moment donné. Il est largement utilisé dans Swing, Ajax, GWT pour répartir les opérations sur, par exemple, les événements de l'interface utilisateur (clics sur les boutons, champs de texte modifiés, etc.).

Dans Swing, vous trouvez des méthodes comme addXXXListener (Listener l), dans GWT vous avez des rappels (Async).

La liste des observateurs étant dynamique, les observateurs peuvent s'inscrire et se désinscrire pendant l'exécution. C'est aussi un bon moyen de découpler l'observable des observateurs, car des interfaces sont utilisées.


9

Si l'intervieweur demande d'implémenter le modèle de conception Observer sans utiliser les classes et interfaces Observer, vous pouvez utiliser l'exemple simple suivant!

MyObserver comme interface d'observateur

interface MyObserver {

    void update(MyObservable o, Object arg);
}

MyObservable en tant que classe 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;
    }

    // ...
}

Votre exemple avec MyObserver et 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

"J'ai essayé de comprendre pourquoi exactement nous avons besoin d'Observer et d'Observable"

Comme les réponses précédentes l'ont déjà indiqué, elles permettent d'abonner un observateur pour recevoir des notifications automatiques d'un observable.

Un exemple d'application où cela peut être utile est dans la liaison de données , disons que vous avez une interface utilisateur qui modifie certaines données, et que vous souhaitez que l'interface utilisateur réagisse lorsque les données sont mises à jour, vous pouvez rendre vos données observables et abonner vos composants d'interface utilisateur à les données

Knockout.js est un framework javascript MVVM qui a un excellent tutoriel de démarrage, pour voir plus d'observables en action, je recommande vraiment de passer par le tutoriel. http://learn.knockoutjs.com/

J'ai également trouvé cet article dans la page de démarrage de Visual Studio 2008 ( Le modèle d'observateur est la base du développement de Model View Controller (MVC) ) http://visualstudiomagazine.com/articles/2013/08/14/the-observer-pattern-in -net.aspx


3

J'ai écrit une courte description du modèle d'observateur ici: http://www.devcodenote.com/2015/04/design-patterns-observer-pattern.html

Un extrait du post:

Modèle d'observateur: il établit essentiellement une relation un-à-plusieurs entre les objets et a une conception faiblement couplée entre des objets interdépendants.

Définition de TextBook: le modèle d'observateur définit une dépendance un-à-plusieurs entre les objets de sorte que lorsqu'un objet change d'état, toutes ses dépendances soient notifiées et mises à jour automatiquement.

Prenons l'exemple d'un service de notification de flux. Les modèles d'abonnement sont les meilleurs pour comprendre le modèle d'observation.


0

Le modèle d'observateur est utilisé lorsqu'il existe une relation un-à-plusieurs entre les objets, par exemple si un objet est modifié, ses objets dépendants doivent être notifiés automatiquement.


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.