EDIT: J'ai écrit ma réponse il y a quelques années. Après l'avoir lu tout à l'heure, j'ai senti que j'avais besoin de le mettre à jour.
je crois que la meilleure approche est d'informer tous les observateurs et laisser les vues décider si elles doivent se mettre à jour ..
Chaque vue sera en mesure de vérifier l'état du modèle et agir en conséquence. De plus, les "args" pourraient être utilisés comme un drapeau pour indiquer ce qui a changé (la vue peut ne pas vouloir se mettre à jour pour chaque petite modification). De cette façon, le modèle ne sait vraiment pas comment et ce que la vue affiche, ils sont découplés.
Une première implémentation ressemblerait à ceci:
public class MyModelV1 extends Observable {
private int value;
public void setValue(int value) {
this.value = value;
setChanged();
notifyObservers();
}
public int getValue() {
return value;
}
}
public class MyViewV1 implements Observer {
public void update(Observable o, Object arg) {
if (o instanceof MyModelV1) {
System.out.println(((MyModelV1) o).getValue());
}
}
}
La vue vérifie simplement le type de l'observable reçu. Cependant, si le modèle possède de nombreux attributs et déclenche la vue pour de nombreux scénarios différents, cette simple vérification peut rafraîchir l'affichage trop souvent.
Une autre approche serait la suivante:
public class MyModelV2 extends Observable {
private int value;
public void setValue(int value) {
this.value = value;
setChanged();
notifyObservers("value");
}
public int getValue() {
return value;
}
}
public class MyViewV2 implements Observer {
public void update(Observable o, Object arg) {
if (o instanceof MyModelV2 && "value".equals(arg)) {
System.out.println(((MyModelV2) o).getValue());
}
}
}
Ici, la notification passe un qualificatif, ce qui permet l'affichage de décider plus précisément quand se rafraîchir. La vue doit toujours vérifier et diffuser le modèle, car il n'y a aucune garantie que l'argument "valeur" n'est pas notifié par un autre modèle (et la distribution échouerait lors de l'exécution).
Mon préféré est quelque chose le long de ces lignes:
public class MyModelV3 extends Observable {
private int value;
public void setValue(int value) {
this.value = value;
setChanged();
Notification.MY_MODEL_VALUE_UPDATED.notifyObserver(this);
}
public int getValue() {
return value;
}
}
public class MyViewV3 implements Observer {
public void update(Observable o, Object arg) {
if (Notification.MY_MODEL_VALUE_UPDATED.equals(arg)) {
MyModelV3 model = Notification.MY_MODEL_VALUE_UPDATED.getModel(o);
System.out.println(model.getValue());
}
}
}
public class Notification<T extends Observable> {
public static final Notification<MyModelV3> MY_MODEL_VALUE_UPDATED = new Notification<MyModelV3>();
private Notification() {
}
public T getModel(Observable o) {
return (T) o;
}
public void notifyObserver(T observable){
observable.notifyObservers(this);
}
}
Ici, la notification envoie un qualificatif fortement typé, qui est lié au modèle. La vue peut utiliser la notification pour extraire un modèle fortement typé (au lieu de diffuser).
Ceci est quelque part entre un observateur et un bus d'événement ..
Il conserve également les choses simples, car il existe des moyens de savoir quels observateurs observent quelle variable. Cela pourrait toutefois sembler compliqué. – mnuzzo
Pourriez-vous me donner un exemple rapide Thomas? Je vous ai voté, mais quelles méthodes seraient mises en œuvre dans la vue, comment seraient-elles notifiées, etc. Merci! – DevDevDev
Voulez-vous dire que tous les observateurs implémenteraient simplement une méthode "notify()", puis ils interrogeraient le modèle pour les données qui les intéressent à chaque fois. Par exemple, notifyObservers() ne fait que parcourir la liste des observateurs et appelle notify(). Chaque observateur extrait les données qu'il souhaite du modèle et met à jour sa vue en conséquence. Comme si la variable A était modifiée, les B-Observers recevraient quand même un appel notify(), et diraient quelque chose comme b = model.getB(), même si b n'a pas changé? – DevDevDev