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 etObserver
est une interface.2) La classe
Observable
maintient une liste deObserver
s.3) Lorsqu'un objet
Observable
est mis à jour, il appelle la méthodeupdate()
de chacun de sesObserver
s 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)
?
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.
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:
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)
.
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é.
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()
.
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
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.
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
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.
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!
interface MyObserver {
void update(MyObservable o, Object arg);
}
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;
}
// ...
}
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);
}
}
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.
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.
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.
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 ...