Das Beobachtermuster ist verwirrend, nicht wahr? Deshalb möchte ich dieses Muster am Beispiel zweier Katzen erklären, die um Reis betteln.
** Tama der Hauskatze ** Tama wohnt im 3. Stock der Wohnung. Der Besitzer lebt alleine. Die Fenster sind oft geschlossen und man geht nicht raus und spielt.
** Streunender Katzentiger ** Der Tiger lebt in einem bestimmten Einkaufsviertel. Ich gehe zu Katzenliebhabern und fange Müll, um Nahrung zu sichern.
Cat.java
public class Cat{//Fachklasse
private Human human;
public void setHuman(Human human){// setObserver()
this.human = human;
}
public void call(){// notifyObservers()
System.out.println("Nya (ich habe Hunger)");
this.human.called();
}
}
Human.java
public class Human{//Beobachterklasse
public void called(){// notify() or update()
System.out.println("Gib knusprig");
}
}
Main.java
public static void main(String[] args) {
Cat tama = new Cat();
Human master = new Human();
tama.setHuman(master);
tama.call();
}
Nya (ich habe Hunger)
Gib knusprig
Es gibt zwei Hauptpunkte des Beobachtermusters. Das erste ist, dass die Subject-Klasse die Observer-Klasse als Mitgliedsvariable hat. Mit anderen Worten, Tama (Katzenklasse) muss den Besitzer (Menschenklasse) kennen. Dies wird durch die Funktion setHuman (= setObserver) dargestellt. Die zweite Möglichkeit besteht darin, die Observer-Klasse aufzurufen, wenn sich die Subject-Klasse ändert. Mit anderen Worten, wenn Sie hungrig sind, rufen Sie den Eigentümer an. Dies wird durch die Funktionen Cat.call und Human.called dargestellt.
Im einfachsten Beobachtermuster kann sich Tama jedoch nur an einen Besitzer erinnern. Wenn Sie versuchen, sich an eine andere Person zu erinnern, vergessen Sie den Besitzer. Der Besitzer wird tränende Augen haben.
Main.java
public static void main(String[] args) {
Cat tama = new Cat();
Human master = new Human();
tama.setHuman(master);
//Der Freund des Besitzers kam zum Spielen
Human friend = new Human();
tama.setHuman(friend);
//Danach werden Sie Ihren Freund um Essen bitten.
tama.call();
}
Tiger können Dinge tun, die Tama nicht konnte. Der Tiger erinnert sich an verschiedene Häuser und scheint sie jedes Mal zu umgehen, wenn er hungrig ist.
Cat.java
public class Cat {//Fachklasse
private final ArrayList<Human> humans = new ArrayList<>();
public void addHuman(Human human){// addObserver()
this.humans.add(human);
}
public void deleteHuman(Human human){// deleteObserver()
this.humans.remove(human);
}
public void call(){// notifyObservers()
System.out.println("Nya (ich habe Hunger)");
for(Human human : this.humans){
human.called();
}
}
}
Human.java
public class Human {//Beobachterklasse
public void called(){// notify() or update()
int dice = new Random().nextInt(99);
if(dice < 50){
System.out.println("Das ist für dich!");
} else {
System.out.println("Heute gibt es nichts ...");
}
}
}
Main.java
public static void main(String[] args) {
Cat tora = new Cat();
Human suzuki = new Human();
Human saito = new Human();
Human kobayashi = new Human();
tora.addHuman(suzuki);
tora.addHuman(saito);
tora.addHuman(kobayashi);
tora.call();
}
Nya (ich habe Hunger)
Heute gibt es nichts ...
Das ist für dich!
Heute gibt es nichts ...
Es gibt drei besonders wichtige Unterschiede zwischen den Tama- und Tora-Codes. Erstens ist die Mitgliedsvariable der Subject-Klasse jetzt eine ArrayList. Dies ermöglicht es Tigern, unter dem Dach mehrerer Häuser um Nahrung zu betteln. Zweitens hat sich die Funktion der Subject-Klasse von setObserver in addObserver geändert. Der Name wurde geändert, da jetzt mehrere Elemente anstelle eines einzelnen Elements festgelegt werden können. Drittens ist es jetzt möglich, die Observer-Klasse nicht nur zu registrieren, sondern auch zu löschen. Die Funktion deleteObserver demonstriert ihre Rolle. Nicht-Besitzer haben eine 50% ige Chance zu füttern, aber nicht die restlichen 50%. Es ist schwer zu wissen, aber ich gehe möglicherweise nicht in ein Haus, das nicht viel füttert (nicht implementiert).
Machen Sie den Tiger-Code vielseitiger und vielseitiger. Dann wird es in Form des Beobachtermusters sein, das Sie oft sehen.
Subject.java
public class Subject {
private final ArrayList<Observer> observers = new ArrayList<>();
public void addObserver(Observer observer){
this.observers.add(observer);
}
public void deleteObserver(Observer observer){
this.observers.remove(observer);
}
public void notifyObservers(){
for(Observer observer : this.observers){
observer.update();
}
}
}
Cat.java
public class Cat extends Subject {
@Override
public void notifyObservers(){
System.out.println("Nya (ich habe Hunger)");
super.notifyObservers();
}
}
Observer.java
public interface Observer{
public void update(); // or notify()
}
Human.java
public class Human implements Observer{
@Override
public void update(){
int dice = new Random().nextInt(99);
if(dice < 50){
System.out.println("Das ist für dich!");
} else {
System.out.println("Heute gibt es nichts ...");
}
}
}
Main.java
public static void main(String[] args) {
Cat tora = new Cat();
Human suzuki = new Human();
Human saito = new Human();
Human kobayashi = new Human();
tora.addObserver(suzuki);
tora.addObserver(saito);
tora.addObserver(kobayashi);
tora.notifyObservers();
}
Nya (ich habe Hunger)
Das ist für dich!
Das ist für dich!
Heute gibt es nichts ...
Es gibt drei Verallgemeinerungen und Änderungen am Tigercode. Zunächst implementiert die Human-Klasse jetzt die Observer-Schnittstelle. Der Grund für das Sandwiching der Observer-Schnittstelle wird mit der dritten Änderung erläutert. Zweitens habe ich die Funktionen der Cat-Klasse als Subject-Klasse extrahiert. Dies macht die flüchtige Cat-Klasse einfacher. Drittens enthält die Subject-Klasse ArrayList jetzt die Observer-Schnittstelle anstelle der Human-Klasse. Durch Aufrufen der Observer.update-Funktion können Sie die Update-Funktion verschiedener Klassen sowie die Human-Klasse aufrufen, wodurch sie vielseitiger wird.
Dieser Kommentar wurde für diejenigen geschrieben, die begonnen haben, Entwurfsmuster zu studieren, das Observer-Muster jedoch schwierig finden. Wenn Sie diesen Kommentar lesen und dann das Klassendiagramm und andere Kommentare erneut lesen, ist es einfacher zu verstehen, was dieses Muster zu tun versucht. Bitte lesen Sie auch Teil 2, wenn Sie möchten. Auch würde ich mich über Ihre Kommentare und Likes freuen.