2009-08-07 6 views
3

Supposons que vous avez 5 ou 6 variables du modèle qui un certain point de vue est intéressé, écrivez-vous des fonctions différentes pour chaque, commeLa meilleure façon d'informer les observateurs dans MVC?

int a; 
int b; 
int c; 

void setA(newA) { 
    a = newA; 
    notifyAObservers(); 
} 

void setB(newB) { 
    b = newB; 
    notifyBObservers(); 
} 

void setC(newC) { 
    b = newC; 
    notifyCObservers(); 
} 

Ou avez-vous juste une notify méthode et perdre un peu du temps CPU

-à-dire au lieu de notifyAObservers et notifyBObservers, il vous suffit notifyObservers

Répondre

6

Je crois que le traditional approach est d'informer tous les observateurs, et laissez-les occuper. C'est parce que vous ne savez pas quels observateurs observent quelle variable (s) - vous savez juste qu'ils veulent être notifiés quand quelque chose change. Cependant, si vous savez ce que les observateurs observent quelles variables, et la performance est critique, alors vous pourriez être en mesure de faire quelque chose comme ce que vous avez.

Dans le modèle Observer traditionnel, les observateurs implémentent une méthode update() appelée par le contrôleur lorsqu'une modification survient. Les Observables (le modèle de données) ont une méthode notifyObservers() qui itère sur les Observers et appelle leur méthode update(). Ensuite, les observateurs obtiennent tout ce dont ils ont besoin et les mises à jour de la vue.

Chaque fois que j'ai implémenté le pattern Observer, je garde simplement une liste d'observateurs et les notifie tous. De cette façon, je n'ai qu'une liste d'observateurs et le reste de la classe ainsi que les différents observateurs peuvent tous changer sans que je n'apporte de changements à la notification de classe observable.

+0

Il conserve également les choses simples, car il existe des moyens de savoir quels observateurs observent quelle variable. Cela pourrait toutefois sembler compliqué. – mnuzzo

+0

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

+0

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

0

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 ..

Questions connexes