JavaRush /Java-Blog /Random-DE /Beobachtervorlage

Beobachtervorlage

Veröffentlicht in der Gruppe Random-DE
Wie die Gang of Four schreibt (unter Bezugnahme auf das Buch „Object-Oriented Design Patterns“ von vier erstklassigen Entwicklern), besteht der Zweck dieses Musters darin, eine Eins-zu-viele-Abhängigkeit zwischen Objekten so zu definieren, dass, wenn die Ändert sich der Status eines Objekts, werden alle davon abhängigen Objekte darüber informiert und automatisch aktualisiert. Dieses Muster wird auch als „Abhängige“ (Untergebene) oder „Publish-Subscribe“ (Herausgeber – Abonnent) bezeichnet. Aber versuchen wir es am Beispiel der katholischen Kirche herauszufinden :) Sie hat Anhänger, die an die Lehren dieser Kirche glauben. Wenn neue Dogmen (verbindliche Glaubensbekenntnisse) und mehr auftauchen, sollten diese Leute darüber Bescheid wissen. Aber wie könnte man das mit diesem Muster in einer Programmiersprache beschreiben? 1. Wir haben die „Stimme der Kirche“ (die Kirche selbst oder den Papst bei Ausstrahlung ex cathedra), also einen bestimmten Sender oder Subjekt, der Neuigkeiten in der Kirche verkündet. 2. Es gibt Gemeindemitglieder dieser Kirche, das heißt einige Beobachter, die über wichtige Ereignisse auf dem Laufenden bleiben möchten. Demnach könnte es heute 1,3 Milliarden Gemeindemitglieder geben, morgen könnten es mehr oder weniger sein. Und Sie müssen nur diejenigen benachrichtigen, die in dieser Kirche sind (keine Notwendigkeit, Atheisten noch einmal zu belästigen :). Das alles könnte man also wie folgt ausdrücken: Es gibt eine Kirche, die ihrer Herde etwas erzählen wird, in das man sich eintragen oder im Gegenteil verlassen kann:
public interface Church {
    void registerParishioner(Parishioner parishioner);
    void removeParishioner(Parishioner parishioner);
    void notifyParishioners();
}
Es gibt eine bestimmte katholische Kirche mit der Umsetzung dieser Methoden sowie Nachrichten und eine Liste von Personen, an die diese Nachrichten gesendet werden sollten:
public class CatholicChurch implements Church {
    private List<parishioner> parishioners;
    private String newsChurch;

    public CatholicChurch() {
        parishioners = new ArrayList<>();
    }

    public void setNewsChurch(String news) {
        this.newsChurch = news;
        notifyParishioners();
    }

    @Override
    public void registerParishioner(Parishioner parishioner) {
        parishioners.add(parishioner);
    }

    @Override
    public void removeParishioner(Parishioner parishioner) {
        parishioners.remove(parishioner);
    }

    @Override
    public void notifyParishioners() {
        for (Parishioner parishioner : parishioners)
            parishioner.update(newsChurch);
    }
}
Es gibt ein Gemeindemitglied, das die Kirche betreten oder verlassen kann (zur Vereinfachung des Codes erlauben wir nur ihm Zutritt :)
public class Parishioner {

    private String name;

    public Parishioner(String name, Church church) {
        this.name = name;
        church.registerParishioner(this);
    }

    void update(String newsChurch) {
        System.out.println(name + "узнал новость: " + newsChurch);
    }
}
Dementsprechend wird es so funktionieren:
public class Main {
    public static void main(String[] args) {
        var catholicChurch = new CatholicChurch();

        new Parishioner("Мартин Лютер", catholicChurch);
        new Parishioner("Жан Кальвин", catholicChurch);

        catholicChurch.setNewsChurch("Инквизиция была ошибкой... месса Mea Culpa 12 марта 2000 года");
    }
}
und das Ergebnis des Programms:
Мартин Лютер узнал новость: Инквизиция была ошибкой... месса Mea Culpa 12 марта 2000 года
Жан Кальвин узнал новость: Инквизиция была ошибкой... месса Mea Culpa 12 марта 2000 года
Diese. Sobald Neuigkeiten in der Kirche erscheinen, werden alle, die zu den registrierten Mitgliedern dieser Kirche gehören, darüber informiert. Was sind die Nachteile dieser Implementierung: 1. Erstens betrifft die Schnittstelle, über die Sie sich registrieren und Nachrichten erhalten können, möglicherweise nicht nur diese Kirche (dies kann erforderlich sein). Daher wäre es möglich, dies sofort in eine separate Observable-Schnittstelle zu verschieben. 2. Das Gleiche könnte man mit Kirchengemeindemitgliedern machen, nämlich die Aktualisierungsmethode in eine separate Schnittstelle verschieben und sie für das gewünschte Gemeindemitglied implementieren. Dann kann diese Methode im Allgemeinen nicht von Gemeindemitgliedern der katholischen Kirche angewendet werden, sondern beispielsweise von denen, die in der Existenz von Elfen leben (gemeint ist die Bewegung „Weg zum Einhorn“). Diese. Erstellen Sie eine Observer-Schnittstelle mit einer Update-Methode. Was wird am Ende passieren:
interface Observable {
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObservers();
}
public class CatholicChurch implements Observable {
    private List<observer> parishioners;
    private String newsChurch;

    public CatholicChurch() {
        parishioners = new ArrayList<>();
    }

    public void setNewsChurch(String news) {
        this.newsChurch = news;
        notifyObservers();
    }

    @Override
    public void registerObserver(Observer o) {
        parishioners.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        parishioners.remove(o);
    }

    @Override
    public void notifyObservers() {
        for (Observer o : parishioners)
            o.update(newsChurch);
    }
}
interface Observer {
    void update (String news);
}
public class Parishioner implements Observer {
    private String name;

    public Parishioner(String name, Observable o) {
        this.name = name;
        o.registerObserver(this);
    }

    @Override
    public void update(String news) {
        System.out.println(name + " узнал новость: " + news);
    }
}
Also: Wir haben die Verbindung zwischen Kirche und Gemeindemitgliedern „geschwächt“, was natürlich nur im Programm gut ist :) Das Subjekt (katholische Kirche) hat nur eine Liste von Zuhörern (Gemeindemitgliedern) und sendet diese Nachrichten, wenn sie Nachrichten (Änderungen) erhalten an seine Zuhörer. Sie können nun eine beliebige andere Einheit erstellen (z. B. eine protestantische Kirche) und die Nachrichten an „Ihre“ Zuhörer senden. Sie müssen auch berücksichtigen, dass Daten der Klasse 2 (genauer gesagt die Observable-Klasse und die Observer-Schnittstelle) im Java-Paket java.util verfügbar waren, jetzt aber mit Java 9 veraltet sind (https://docs.oracle). com/en/java/javase/15/docs/api/java.base/java/util/Observable.html): Veraltet. Diese Klasse und die Observer-Schnittstelle sind veraltet. Das von Observer und Observable unterstützte Ereignismodell ist recht begrenzt, die Reihenfolge der von Observable übermittelten Benachrichtigungen ist nicht spezifiziert und Zustandsänderungen stehen nicht in einer Eins-zu-Eins-Entsprechung mit Benachrichtigungen. Für ein umfassenderes Ereignismodell sollten Sie die Verwendung des Pakets java.beans in Betracht ziehen. Für eine zuverlässige und geordnete Nachrichtenübermittlung zwischen Threads sollten Sie die Verwendung einer der gleichzeitigen Datenstrukturen im Paket java.util.concurrent in Betracht ziehen. Informationen zur Programmierung im Stil reaktiver Streams finden Sie in der Flow-API. Daher besteht keine Notwendigkeit, sie zu verwenden. Sie können stattdessen auch andere verwenden, aber die Essenz des Musters ändert sich nicht. Versuchen wir beispielsweise, PropertyChangeListener aus dem Paket java.beans zu verwenden (um keine unnötigen Klassen zu schreiben, die bereits geschrieben wurden). Mal sehen, wie es sein wird: Fachklasse:
public class CatholicChurch {
    private String news;
    // используя support мы можем добавлять oder удалять наших прихожан (слушателей)
    private PropertyChangeSupport support;

    public CatholicChurch() {
        support = new PropertyChangeSupport(this);
    }
    public void addPropertyChangeListener(PropertyChangeListener pcl) {
        support.addPropertyChangeListener(pcl);
    }

    public void removePropertyChangeListener(PropertyChangeListener pcl) {
        support.removePropertyChangeListener(pcl);
    }

    public void setNews(String value) {
        support.firePropertyChange("news", this.news, value);
        this.news = value;
    }
}
und die Listener-Klasse:
public class Parishioner implements PropertyChangeListener {
    private String name;

    public Parishioner(String name) {
        this.name = name;
    }

    public void propertyChange(PropertyChangeEvent evt) {
        this.setNews((String) evt.getNewValue());
    }

    public void setNews(String news) {
        System.out.println(name + " узнал новость: " + news);
    }
}
Wenn wir den folgenden Code ausführen:
public static void main(String[] args) {
    CatholicChurch observable = new CatholicChurch();

    observable.addPropertyChangeListener(new Parishioner("Мартин Лютер"));
    observable.addPropertyChangeListener(new Parishioner("Жан Кальвин"));

    observable.setNews("Дева Мария имеет непорочное зачатие... булла Ineffabilis Deus... 8 декабря 1854 года Папа Пий IX");
    observable.setNews("Папа непогрешим... не всегда конечно, а только когда транслирует учение церкви ex cathedra... Первый Ватиканский собор 1869 год");
}
Wir erhalten folgendes Ergebnis:
Martin Luther erfuhr die Nachricht: Die Jungfrau Maria ist von der Unbefleckten Empfängnis... Bulle Ineffabilis Deus... 8. Dezember 1854 Papst Pius IX. Johannes Calvin erfuhr die Nachricht: Die Jungfrau Maria ist von der Unbefleckten Empfängnis... Bulle Ineffabilis Deus ... 8. Dezember 1854 Papst Pius IX. Martin Luther erfuhr die Nachricht: Der Papst ist unfehlbar ... natürlich nicht immer, aber nur, wenn er die Lehren der Kirche ex cathedra verbreitet ... Erstes Vatikanisches Konzil 1869 Johannes Calvin erfuhr die Nachrichten: Der Papst ist unfehlbar... nicht immer natürlich, aber nur, wenn er die Lehren der Kirche ex cathedra überträgt... Erstes Vatikanisches Konzil 1869
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION