[GO] Beobachtermuster von Nyanko Teil 1 verstanden

Überblick

Das Beobachtermuster ist verwirrend, nicht wahr? Deshalb möchte ich dieses Muster am Beispiel zweier Katzen erklären, die um Reis betteln. IMG_0751.JPG

Nyanko erscheint

** 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. neko_furikaeri.png

** Streunender Katzentiger ** Der Tiger lebt in einem bestimmten Einkaufsviertel. Ich gehe zu Katzenliebhabern und fange Müll, um Nahrung zu sichern. run_cat.png

Ich denke, dies ist wahrscheinlich das einfachste Beobachtermuster

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

Kommentar

uml1.png

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();
    }

Grundstruktur des Beobachtermusters

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

Kommentar

uml2.png

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

Verallgemeinerung

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

Kommentar

uml3.png

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.

Ergänzung

  1. Die Aktualisierungsfunktion, die manchmal als Benachrichtigungsfunktion angezeigt wird, zeigt dieselbe Funktionalität.
  2. In Java ist die Subject-Klasse die Observable-Klasse und die Observer-Schnittstelle hat denselben Namen. Ich habe es vorbereitet.
  3. Die Subject-Klasse wird manchmal als Event-Handler bezeichnet, und die Observer-Klasse wird manchmal als Event-Listener bezeichnet.

abschließend

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.

Recommended Posts

Beobachtermuster von Nyanko Teil 1 verstanden
Beobachtermuster, das in Nyanko Teil 2 zu sehen ist
Entwurfsmuster #Observer
Beobachtermuster in Java
Beispielquelle für das von Java, PHP, Python realisierte Observer-Muster
Ton erzeugen durch Programmieren von Teil 2