web-dev-qa-db-fra.com

Quand devrions-nous utiliser Observer et Observable?

Un interviewer m'a demandé:

Qu'est-ce que Observer et Observable et quand devrions-nous les utiliser?

Comme je n'étais pas au courant de ces termes, lorsque je suis rentré chez moi et que j'ai commencé à rechercher Google à propos de Observer et Observable, j'ai trouvé des éléments de ressources différentes:

1) Observable est une classe et Observer est une interface.

2) La classe Observable maintient une liste de Observers.

3) Lorsqu'un objet Observable est mis à jour, il appelle la méthode update() de chacun de ses Observers pour le notifier. 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 Observer et Observable? A quoi servent les méthodes setChanged() et notifyObservers(message)?

181
Ravi

Vous avez un exemple concret d'étudiant et de messageBoard. L'étudiant s'inscrit en s'ajoutant à la liste des observateurs souhaitant ê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 informe que l'événement s'est produit.

Pensez Twitter. Lorsque vous dites que vous voulez 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 peut ne pas être parfaite, car Twitter est plus susceptible d'être un médiateur. Mais cela illustre le propos.

243
duffymo

En termes très simples (car les autres réponses vous renvoient de toute façon à tous les modèles de conception officiels, regardez-les pour plus de détails):

Si vous voulez avoir une classe qui est surveillée par d'autres classes de l'écosystème de votre programme, vous dites que vous voulez que la classe soit observable. C'est à dire. il se peut que vous souhaitiez diffuser certains changements dans son état 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 associée aux classes intéressées à l'observer. Peu importe qui c'est, tant que cela remplit certains critères. (Imaginez que c'est une station de radio, peu importe qui écoute, tant qu'une radio FM est réglée sur leur fréquence). Pour ce faire, nous utilisons une interface, appelée Observer. 

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

La dernière chose à faire est de savoir comment la classe Observable saura qui est intéressé? La classe Observable doit donc proposer un mécanisme permettant aux observateurs de faire connaître leur intérêt. Une méthode telle que addObserver(Observer o) ajoute en interne Observer à la liste des observateurs. Ainsi, lorsqu'un événement important se produit, il parcourt la liste et appelle la méthode de notification correspondante de l'interface Observer de chaque instance de la liste.

Il se peut que dans l'interview, ils ne vous aient pas explicitement interrogé sur les Java.util.Observer et Java.util.Observable, mais sur le concept générique. Le concept est un modèle de conception que Java fournit directement à l’assistance 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 quand vous en avez besoin).

METTRE À JOUR

En réponse à votre commentaire, la classe Java.util.Observable présente les fonctionnalités suivantes:

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

  2. Maintenir un état interne, en 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 la Observable a été modifiée de la partie où vous notifiez les modifications. (Par exemple, il est utile si plusieurs modifications sont en cours et que vous souhaitez uniquement notifier à la fin du processus plutôt qu'à chaque petite étape). Ceci est fait par setChanged(). Donc, vous appelez cela quand vous avez changé quelque chose en Observable et que vous voulez que le reste de Observers en soit informé.

  3. Notifier tous les observateurs que la Observable spécifique a changé d'état. Ceci est fait par notifyObservers(). Ceci vérifie si l'objet a réellement changé (c'est-à-dire qu'un appel à setChanged() a été effectué) avant de procéder à la notification. Il existe 2 versions, une sans argument et une avec un argument Object, au cas où vous souhaiteriez transmettre des informations supplémentaires avec la notification. En interne, il se produit qu’il parcourt simplement la liste des instances de Observer et appelle la méthode update(Observable o, Object arg) pour chacune d’elles. Cela indique à la Observer qui était l'objet observable qui a changé (vous pouvez en observer plus d'un) et au Object arg supplémentaire pour éventuellement transporter des informations supplémentaires (transmises via notifyObservers().

53
jbx

Définition

Le modèle observateur est utilisé lorsqu'il existe une relation d'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. Disons que votre adresse permanente est modifiée, vous devez alors en informer l'autorité du passeport et l'autorité de la carte panoramique. Ainsi, l'autorité du passeport et l'autorité de la carte panoramique sont des observateurs et vous êtes un sujet.

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

Quand l'utiliser:

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.

Étape 1

Créer une classe de sujet.

Sujet.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éer une classe d'observateur.

Observer.Java

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

Étape 3

Créer des classes d'observateur 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 Subject et 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

Hex String: F

Chaîne octale: 17

Chaîne binaire: 1111

Deuxième changement d'état: 10

Hex String: A

Chaîne octale: 12

Chaîne binaire: 1010

32
Mubarak

Ils font partie du modèle de conception d'observateur . En général, un ou plusieurs observateurs sont informés des modifications apportées à un observable. C'est une notification que "quelque chose" est arrivé, 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 connectables.

10
Andy

Si l'intervieweur demande à mettre en œuvre Modèle de conception Observer sans utiliser les classes et interfaces Observer, vous pouvez utiliser l'exemple simple suivant! 

MyObserver en tant qu'interface d'observateur

interface MyObserver {

    void update(MyObservable o, Object arg);
}

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

}
9
Habeeb Perwad

Observer a.k.a un rappel 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 et GWT pour les opérations de répartition, par exemple. Événements d'interface utilisateur (clics sur les boutons, champs de texte modifiés, etc.).

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

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

9
Pawel Solarski

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

Un extrait du message:

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.

TextBook Définition: Le modèle Observer définit une dépendance un à plusieurs entre des objets de sorte que lorsqu'un objet change d'état, tous ses dépendants soient notifiés et mis à jour automatiquement.

Considérons un service de notification de fil par exemple. Les modèles d'abonnement sont les meilleurs pour comprendre le modèle d'observateur.

3
Abhishek Jain

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

0
Swapnil Sharma

Depuis Java9, les deux interfaces sont obsolètes, ce qui signifie que vous ne devriez plus les utiliser. Voir Observer est obsolète en Java 9. Que devrions-nous utiliser à la place?

Cependant, vous pouvez toujours avoir des questions d'entrevue à leur sujet ...

0
tkruse