Le modèle d’observateur est un modèle de conception comportementale. L'utilisation du modèle Observer est utile lorsque vous êtes intéressé par l'état d'un objet et que vous souhaitez être averti à chaque fois qu'il change. Dans le modèle d'observateur, l'objet qui observe l'état d'un autre objet est appelé l'observateur et l'objet observé est appelé le sujet. Selon les règles du GoF, l'intention du modèle Observer est :
Copiez le code comme suit :
Définissez une relation de dépendance un-à-plusieurs entre les objets. Si l'état d'un objet change, les autres objets associés seront notifiés et automatiquement mis à jour.
Les sujets contiennent des observateurs qui doivent être avertis lorsque leur état change. Par conséquent, il devrait fournir aux observateurs des méthodes pour s’inscrire et se désinscrire. Lorsque le sujet (observé) change, il doit également inclure une méthode pour avertir tous les observateurs. Lorsque vous avertissez les observateurs, vous pouvez envoyer des mises à jour ou proposer une autre méthode pour obtenir des mises à jour.
Les observateurs doivent disposer d'une méthode qui définit l'objet observateur et peut être utilisée par l'observé pour le notifier des mises à jour.
JAVA fournit des moyens intégrés pour implémenter le modèle d'observateur, les interfaces java.util.Observable et java.util.Observer. Cependant, ils ne sont pas très largement utilisés. Parce que cette implémentation est trop simple, la plupart du temps nous ne voulons pas que la dernière classe étendue implémente simplement le modèle d'observateur, car les classes JAVA ne peuvent pas hériter plusieurs fois.
Le service de messagerie Java Messages Service (JMS) utilise le mode observateur et le mode commande pour réaliser la publication et l'abonnement de données entre différents programmes.
Le framework modèle-vue-contrôle MVC utilise également le modèle d'observateur, traitant le modèle comme l'observé et la vue comme l'observateur. Les vues peuvent s'enregistrer elles-mêmes dans le modèle pour recevoir les modifications apportées au modèle.
Exemple de modèle d'observateur
Dans cet exemple, nous réaliserons une discussion sur un sujet simple et les observateurs pourront s'inscrire à ce sujet. Tout changement résultant de la soumission de contenu sur ce sujet sera notifié à tous les observateurs enregistrés.
En fonction des besoins des observateurs du Sujet, il s'agit d'implémenter une interface Sujet de base. Cette interface spécifie une série de méthodes spécifiques qui doivent être implémentées dans la classe spécifique qui implémente ensuite l'interface.
Copiez le code comme suit :
package com.journaldev.design.observer;
interface publique Sujet {
//méthodes pour enregistrer et désinscrire les observateurs
registre vide public (Observateur obj);
public void unregister (Observateur obj);
//méthode pour informer les observateurs du changement
public void notifyObservers();
// méthode pour obtenir des mises à jour du sujet
Objet public getUpdate (Observateur obj);
}
Créez maintenant un observateur associé. Il a besoin d'une méthode pour attacher le sujet à un observateur. Des méthodes supplémentaires peuvent accepter les notifications de changement de sujet.
Copiez le code comme suit :
package com.journaldev.design.observer;
Observateur d'interface publique {
//méthode de mise à jour de l'observateur, utilisée par sujet
mise à jour publique vide ();
//attacher au sujet à observer
public void setSubject (Sujet sub);
}
Cette connexion a été établie. Mettez maintenant en œuvre le thème concret.
Copiez le code comme suit :
package com.journaldev.design.observer;
importer java.util.ArrayList ;
importer java.util.List ;
classe publique MyTopic implémente le sujet {
observateurs privés List<Observer> ;
message de chaîne privé ;
booléen privé modifié ;
Objet final privé MUTEX= new Object();
public MonSujet(){
this.observers=new ArrayList<>();
}
@Outrepasser
registre vide public (Observateur obj) {
if(obj == null) throw new NullPointerException("Null Observer");
if(!observers.contains(obj)) observers.add(obj);
}
@Outrepasser
public void unregister (Observateur obj) {
observateurs.remove(obj);
}
@Outrepasser
public void notifyObservers() {
List<Observateur> observateursLocal = null;
//la synchronisation est utilisée pour s'assurer que tout observateur enregistré après la réception du message n'est pas notifié
synchronisé (MUTEX) {
si (!changé)
retour;
observersLocal = new ArrayList<>(this.observers);
this.changed=false ;
}
pour (Observateur obj : observateursLocal) {
obj.update();
}
}
@Outrepasser
Objet public getUpdate (Observateur obj) {
renvoie ce.message ;
}
// méthode pour poster un message sur le sujet
public void postMessage(String msg){
System.out.println("Message publié sur le sujet :"+msg);
this.message=msg;
this.changed=true ;
notifyObservateurs();
}
}
L'implémentation des méthodes d'enregistrement et de désenregistrement des observateurs est très simple. La méthode supplémentaire postMessage() sera utilisée par le client pour soumettre un message sous forme de chaîne à ce sujet. Notez que les variables booléennes sont utilisées pour suivre les changements dans l'état du sujet et informer les observateurs de ces changements. Cette variable est nécessaire car s'il n'y a pas de mise à jour, mais que quelqu'un appelle la méthode notifyObservers(), il ne peut pas envoyer d'informations de notification d'erreur aux observateurs.
De plus, il convient de noter que la synchronisation est utilisée dans notifyObservers() pour garantir que les notifications ne peuvent être envoyées qu'aux observateurs enregistrés avant que le message ne soit publié sur le sujet.
Voici l’implémentation de l’observateur. Ils se concentreront toujours sur l’objet sujet.
Copiez le code comme suit :
package com.journaldev.design.observer;
classe publique MyTopicSubscriber implémente Observer {
nom de chaîne privé ;
sujet privé ;
public MyTopicSubscriber (String nm) {
this.name=nm;
}
@Outrepasser
mise à jour publique vide() {
String msg = (String) topic.getUpdate(this);
si(msg==null){
System.out.println(name+":: Aucun nouveau message");
}autre
System.out.println(name+":: Message consommateur ::"+msg);
}
@Outrepasser
public void setSubject(Sujet sous) {
this.topic=sub;
}
}
Notez que l'implémentation de la méthode update() utilise la méthode getUpdate() de l'observateur pour gérer les messages mis à jour. Passer le message en tant que paramètre à la méthode update() doit être évité ici.
Voici un programme de test simple pour vérifier l'implémentation de la classe topic.
Copiez le code comme suit :
package com.journaldev.design.observer;
classe publique ObserverPatternTest {
public static void main (String[] arguments) {
//créer un sujet
Sujet MyTopic = new MyTopic();
//créer des observateurs
Observateur obj1 = new MyTopicSubscriber("Obj1");
Observateur obj2 = new MyTopicSubscriber("Obj2");
Observateur obj3 = new MyTopicSubscriber("Obj3");
//enregistrer les observateurs sur le sujet
sujet.register(obj1);
sujet.register(obj2);
sujet.register(obj3);
//attacher l'observateur au sujet
obj1.setSubject(sujet);
obj2.setSubject(sujet);
obj3.setSubject(sujet);
// vérifie si une mise à jour est disponible
obj1.update();
// envoie maintenant un message au sujet
topic.postMessage("Nouveau message");
}
}
Voici le résultat ci-dessus :
Copiez le code comme suit :
Obj1 : Aucun nouveau message
Message publié sur le sujet :Nouveau message
Obj1 : Message consommateur : Nouveau message
Obj2 :: Message consommateur :: Nouveau message
Obj3::Consommation de message::Nouveau message</pre>
Diagramme UML du modèle Observer
Le modèle d’observateur est également appelé modèle de publication-abonnement. Certaines applications spécifiques en JAVA sont les suivantes :
1.java.util.EventListener dans Swing
2.javax.servlet.http.HttpSessionBindingListener
3.javax.servlet.http.HttpSessionAttributeListener
Les modes ci-dessus sont tous des modes d’observateur. J'espère que vous l'aimez déjà. Partagez vos sentiments dans les commentaires ou partagez-les avec les autres.