JavaRush /Java Blog /Random-ID /Templat pengamat

Templat pengamat

Dipublikasikan di grup Random-ID
Seperti yang ditulis oleh Gang of Four (mengacu pada buku “Pola Desain Berorientasi Objek” oleh 4 pengembang terkemuka), tujuan dari pola ini adalah untuk mendefinisikan ketergantungan satu-ke-banyak antar objek sedemikian rupa sehingga ketika keadaan suatu objek berubah, semua orang yang bergantung padanya akan diberitahu tentang hal ini dan diperbarui secara otomatis. Pola ini disebut juga: Tanggungan (bawahan) atau Publikasikan-Berlangganan (penerbit – pelanggan). Tapi mari kita coba mencari tahu dengan menggunakan contoh Gereja Katolik :) Ada pengikutnya yang percaya pada ajaran gereja ini. Ketika ada dogma baru (keyakinan wajib) dan lebih banyak lagi yang muncul, orang-orang ini harus mengetahuinya. Tapi bagaimana hal ini bisa dijelaskan dalam bahasa pemrograman menggunakan pola ini? 1. Kita memiliki “suara gereja” (gereja itu sendiri atau Paus ketika menyiarkan ex cathedra), yaitu penyiar atau subjek tertentu yang mengumumkan berita di dalam gereja. 2. Ada umat paroki di gereja ini, yaitu beberapa pengamat yang ingin mengetahui peristiwa-peristiwa penting. Oleh karena itu, saat ini mungkin ada 1,3 miliar umat paroki, dan besok mungkin ada lebih atau kurang. Dan anda hanya perlu memberitahukan kepada yang ada di gereja ini (tidak perlu repot atheis lagi :). Dengan demikian, semua ini dapat diungkapkan sebagai berikut: Ada sebuah gereja yang akan memberitahu jemaatnya tentang sesuatu, di mana Anda dapat mendaftar atau, sebaliknya, meninggalkannya:
public interface Church {
    void registerParishioner(Parishioner parishioner);
    void removeParishioner(Parishioner parishioner);
    void notifyParishioners();
}
Ada Gereja Katolik tertentu yang menerapkan metode ini, serta berita dan daftar orang kepada siapa berita ini harus disiarkan:
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);
    }
}
Ada umat paroki yang bisa masuk atau keluar gereja (untuk menyederhanakan kode, kami hanya mengizinkan dia masuk :)
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);
    }
}
Oleh karena itu, beginilah cara kerjanya:
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 года");
    }
}
dan hasil dari program ini:
Мартин Лютер узнал новость: Инквизиция была ошибкой... месса Mea Culpa 12 марта 2000 года
Жан Кальвин узнал новость: Инквизиция была ошибкой... месса Mea Culpa 12 марта 2000 года
Itu. Segera setelah berita muncul di gereja, setiap orang yang termasuk dalam daftar anggota terdaftar gereja ini akan diberitahu tentang hal itu. Apa kerugian penerapan ini: 1. Pertama, antarmuka tempat Anda dapat mendaftar dan menerima berita mungkin tidak hanya berlaku untuk gereja ini (ini mungkin diperlukan). Oleh karena itu, dimungkinkan untuk segera memindahkannya ke antarmuka Observable yang terpisah. 2. Hal yang sama dapat dilakukan dengan umat paroki, yaitu memindahkan metode pembaruan ke antarmuka terpisah dan mengimplementasikannya untuk umat yang diinginkan. Maka cara ini secara umum tidak dapat digunakan oleh umat paroki Gereja Katolik, tetapi misalnya oleh mereka yang hidup dalam keberadaan elf (artinya gerakan “Jalan Menuju Unicorn”). Itu. buat antarmuka Pengamat dengan metode pembaruan. Apa yang akan terjadi pada akhirnya:
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);
    }
}
Jadi: Kami telah “melemahkan hubungan” antara gereja dan umat paroki, yang tentu saja hanya baik dalam pemrograman :) Subjek (Gereja Katolik) hanya memiliki daftar pendengar (umat paroki) dan ketika menerima berita (perubahan), menyiarkan berita ini kepada para pendengarnya. Anda sekarang dapat membuat entitas lain (misalnya, gereja Protestan) dan menyiarkan berita tersebut kepada pendengar “Anda”. Anda juga perlu memperhitungkan bahwa data kelas 2 (lebih tepatnya, kelas Observable dan antarmuka Observer) tersedia dalam paket java.util java, tetapi sekarang sudah tidak digunakan lagi dengan java 9 (https://docs.Oracle. com/en/java/javase/15/docs/api/java.base/java/util/Observable.html): Tidak digunakan lagi. Kelas ini dan antarmuka Pengamat sudah tidak digunakan lagi. Model peristiwa yang didukung oleh Observer dan Observable cukup terbatas, urutan notifikasi yang dikirimkan oleh Observable tidak ditentukan, dan perubahan status tidak sesuai dengan notifikasi. Untuk model acara yang lebih kaya, pertimbangkan untuk menggunakan paket java.beans. Untuk pengiriman pesan yang andal dan teratur antar thread, pertimbangkan untuk menggunakan salah satu struktur data bersamaan dalam paket java.util.concurrent. Untuk pemrograman gaya aliran reaktif, lihat Flow API. Oleh karena itu tidak perlu menggunakannya. Dan Anda dapat menggunakan yang lain sebagai gantinya, tetapi inti dari polanya tidak akan berubah. Sebagai contoh, mari kita coba menggunakan PropertyChangeListener (agar tidak menulis kelas-kelas yang tidak diperlukan yang telah ditulis) dari paket java.beans. Mari kita lihat bagaimana jadinya: kelas mata pelajaran:
public class CatholicChurch {
    private String news;
    // используя support мы можем добавлять or удалять наших прихожан (слушателей)
    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;
    }
}
dan kelas pendengar:
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);
    }
}
Jika kita mengeksekusi kode berikut:
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 год");
}
Kami mendapatkan hasil berikut:
Martin Luther mengetahui berita: Perawan Maria Dikandung Tanpa Noda... banteng Ineffabilis Deus... 8 Desember 1854 Paus Pius IX Yohanes Calvin mengetahui berita: Perawan Maria Dikandung Tanpa Noda... Banteng Ineffabilis Deus ... 8 Desember 1854 Paus Pius IX Martin Luther mengetahui berita: Paus itu sempurna... tidak selalu tentu saja, tetapi hanya ketika dia menyiarkan ajaran gereja ex cathedra... Konsili Vatikan Pertama 1869 John Calvin mengetahui berita: Paus adalah infalibel... tentu saja tidak selalu, tetapi hanya ketika ia menyiarkan ajaran gereja ex cathedra... Konsili Vatikan Pertama 1869
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION