Observer Pattern ist eines der Verhaltensmuster. Das Observer-Designmuster ist nützlich, wenn Sie am Zustand eines Objekts interessiert sind und benachrichtigt werden möchten, wenn sich etwas ändert. Im Observer-Muster werden die Objekte, die den Zustand eines anderen Objekts beobachten, als Observer bezeichnet und das beobachtete Objekt als Subject.
Observer-Designmuster
Laut GoF ist das Ziel des Observer-Designmusters;
Eine Eins-zu-viele-Abhängigkeit zwischen Objekten definieren, sodass, wenn sich der Zustand eines Objekts ändert, alle seine Abhängigen automatisch benachrichtigt und aktualisiert werden.
Subjekt enthält eine Liste von Beobachtern, die über jede Änderung in seinem Zustand benachrichtigt werden sollen. Daher sollte es Methoden bereitstellen, mit denen Beobachter sich registrieren und abmelden können. Das Subjekt enthält auch eine Methode, um alle Beobachter über Änderungen zu benachrichtigen. Dabei kann es entweder das Update senden, während es den Beobachter benachrichtigt, oder es kann eine andere Methode bereitstellen, um das Update abzurufen. Der Beobachter sollte eine Methode haben, um das zu beobachtende Objekt festzulegen, und eine andere Methode, die vom Subjekt verwendet wird, um sie über Aktualisierungen zu benachrichtigen. Java bietet eine eingebaute Plattform zur Implementierung des Beobachtermusters durch die Klasse java.util.Observable und das Interface java.util.Observer. Es wird jedoch nicht weit verbreitet verwendet, weil die Implementierung wirklich einfach ist und wir die meiste Zeit nicht möchten, eine Klasse nur für die Implementierung des Beobachtermusters zu erweitern, da Java keine mehrfache Vererbung in Klassen ermöglicht. Java Message Service (JMS) verwendet das Beobachtermuster zusammen mit dem Vermittlermuster, um Anwendungen die Möglichkeit zu geben, Daten bei anderen Anwendungen zu abonnieren und zu veröffentlichen. Model-View-Controller (MVC)-Frameworks verwenden ebenfalls das Beobachtermuster, wobei das Modell das Subjekt ist und Ansichten Beobachter sind, die sich registrieren können, um über Änderungen am Modell informiert zu werden.
Beobachtermuster Java Beispiel
Für unser Beispielprogramm zum Beobachtermuster in Java würden wir ein einfaches Thema implementieren, zu dem Beobachter sich registrieren können. Immer wenn eine neue Nachricht an das Thema gesendet wird, werden alle registrierten Beobachter benachrichtigt und sie können die Nachricht verarbeiten. Basierend auf den Anforderungen des Subjekts, hier ist das Basisschnittstellen-Interface Subject, das die Vertragsmethoden definiert, die von jedem konkreten Subjekt implementiert werden müssen.
package com.journaldev.design.observer;
public interface Subject {
// Methoden zur Registrierung und Deregistrierung von Beobachtern
public void register(Observer obj);
public void unregister(Observer obj);
// Methode zur Benachrichtigung von Beobachtern über Änderungen
public void notifyObservers();
// Methode zum Abrufen von Updates vom Subjekt
public Object getUpdate(Observer obj);
}
Als nächstes werden wir einen Vertrag für den Beobachter erstellen. Es wird eine Methode geben, um das Subjekt an den Beobachter anzuhängen, und eine weitere Methode, die vom Subjekt verwendet wird, um über jede Änderung zu benachrichtigen.
package com.journaldev.design.observer;
public interface Observer {
// Methode zur Aktualisierung des Beobachters, die vom Subjekt verwendet wird
public void update();
// Anhängen an das Subjekt, um zu beobachten
public void setSubject(Subject sub);
}
Jetzt ist unser Vertrag bereit. Lassen Sie uns mit der konkreten Implementierung unseres Themas fortfahren.
package com.journaldev.design.observer;
import java.util.ArrayList;
import java.util.List;
public class MyTopic implements Subject {
private List observers;
private String message;
private boolean changed;
private final Object MUTEX= new Object();
public MyTopic(){
this.observers=new ArrayList<>();
}
@Override
public void register(Observer obj) {
if(obj == null) throw new NullPointerException("Null Observer");
synchronized (MUTEX) {
if(!observers.contains(obj)) observers.add(obj);
}
}
@Override
public void unregister(Observer obj) {
synchronized (MUTEX) {
observers.remove(obj);
}
}
@Override
public void notifyObservers() {
List observersLocal = null;
// Synchronisation wird verwendet, um sicherzustellen, dass kein Beobachter benachrichtigt wird, der nach Erhalt der Nachricht registriert wurde
synchronized (MUTEX) {
if (!changed)
return;
observersLocal = new ArrayList<>(this.observers);
this.changed=false;
}
for (Observer obj : observersLocal) {
obj.update();
}
}
@Override
public Object getUpdate(Observer obj) {
return this.message;
}
// Methode zum Posten von Nachrichten zum Thema
public void postMessage(String msg){
System.out.println("Message Posted to Topic:"+msg);
this.message=msg;
this.changed=true;
notifyObservers();
}
}
Die Implementierungsmethode zum Registrieren und Abmelden eines Beobachters ist sehr einfach, die zusätzliche Methode ist postMessage(), die von der Client-Anwendung verwendet wird, um eine String-Nachricht an das Thema zu senden. Beachten Sie die boolesche Variable, um den Zustandswechsel des Themas zu verfolgen und bei der Benachrichtigung von Beobachtern zu verwenden. Diese Variable ist erforderlich, damit bei keinem Update und Aufruf der Methode notifyObservers() keine falschen Benachrichtigungen an die Beobachter gesendet werden. Beachten Sie auch die Verwendung von Synchronisierung in der Methode notifyObservers(), um sicherzustellen, dass die Benachrichtigung nur an die vor der Veröffentlichung der Nachricht registrierten Beobachter gesendet wird. Hier ist die Implementierung der Beobachter, die über das Thema wachen.
package com.journaldev.design.observer;
public class MyTopicSubscriber implements Observer {
private String name;
private Subject topic;
public MyTopicSubscriber(String nm){
this.name=nm;
}
@Override
public void update() {
String msg = (String) topic.getUpdate(this);
if(msg == null){
System.out.println(name+":: No new message");
}else
System.out.println(name+":: Consuming message::"+msg);
}
@Override
public void setSubject(Subject sub) {
this.topic=sub;
}
}
Beachten Sie die Implementierung der Methode update(), in der die Methode getUpdate() des Subjekts aufgerufen wird, um die zu verarbeitende Nachricht zu erhalten. Wir hätten diesen Aufruf vermeiden können, indem wir die Nachricht als Argument an die Methode update() übergeben. Hier ist ein einfaches Testprogramm zum Verbrauch unserer Thema-Implementierung.
package com.journaldev.design.observer;
public class ObserverPatternTest {
public static void main(String[] args) {
//Thema erstellen
MyTopic topic = new MyTopic();
//Beobachter erstellen
Observer obj1 = new MyTopicSubscriber("Obj1");
Observer obj2 = new MyTopicSubscriber("Obj2");
Observer obj3 = new MyTopicSubscriber("Obj3");
//Beobachter beim Thema registrieren
topic.register(obj1);
topic.register(obj2);
topic.register(obj3);
//Beobachter dem Thema zuordnen
obj1.setSubject(topic);
obj2.setSubject(topic);
obj3.setSubject(topic);
//Überprüfen, ob ein Update verfügbar ist
obj1.update();
//Jetzt Nachricht an das Thema senden
topic.postMessage("New Message");
}
}
Wenn wir das obige Programm ausführen, erhalten wir folgende Ausgabe.
Obj1:: No new message
Message Posted to Topic:New Message
Obj1:: Consuming message::New Message
Obj2:: Consuming message::New Message
Obj3:: Consuming message::New Message
Java-Observer-Muster Klassendiagramm
Das Observer-Entwurfsmuster wird auch als Publish-Subscribe-Muster bezeichnet. Einige seiner Implementierungen sind;
- java.util.EventListener in Swing
- javax.servlet.http.HttpSessionBindingListener
- javax.servlet.http.HttpSessionAttributeListener
Das ist alles zum Observer-Entwurfsmuster in Java. Ich hoffe, es hat Ihnen gefallen. Teilen Sie Ihre Liebe mit Kommentaren und indem Sie es mit anderen teilen.
Source:
https://www.digitalocean.com/community/tutorials/observer-design-pattern-in-java