JavaRush /Java Blog /Random-TL /Template ng tagamasid

Template ng tagamasid

Nai-publish sa grupo
Tulad ng isinusulat ng Gang of Four (tumutukoy sa aklat na "Object-Oriented Design Patterns" ng 4 na nangungunang developer), ang layunin ng pattern na ito ay tukuyin ang isa-sa-maraming dependency sa pagitan ng mga bagay sa paraang kapag ang nagbabago ang estado ng isang bagay, lahat ng umaasa dito ay inaabisuhan tungkol dito at awtomatikong ina-update. Ang pattern na ito ay tinatawag ding: Dependents (subordinates) o Publish-Subscribe (publisher - subscriber). Ngunit subukan nating alamin ito gamit ang halimbawa ng Simbahang Katoliko :) Mayroon itong mga tagasunod na naniniwala sa mga turo ng simbahang ito. Kapag lumitaw ang anumang bagong dogma (obligatory creed) at higit pa, dapat malaman ng mga taong ito ang tungkol sa kanila. Ngunit paano ito mailalarawan sa isang programming language gamit ang pattern na ito? 1. Mayroon tayong "boses ng simbahan" (ang simbahan mismo o ang Pope kapag nagbo-broadcast ng ex cathedra), iyon ay, isang partikular na tagapagbalita o paksa na nag-aanunsyo ng balita sa simbahan. 2. May mga parokyano ng simbahang ito, iyon ay, ilang tagamasid na gustong magkaroon ng kamalayan sa mahahalagang pangyayari. Alinsunod dito, ngayon ay maaaring mayroong 1.3 bilyong mga parokyano, at bukas ay maaaring higit pa o mas kaunti. At kailangan mo lang ipaalam sa mga nasa simbahang ito (no need to bother atheists again :). Kaya, ang lahat ng ito ay maaaring ipahayag tulad ng sumusunod: May isang simbahan na magsasabi sa kanyang kawan tungkol sa isang bagay, kung saan maaari kang magparehistro o, sa kabaligtaran, iwanan ito:
public interface Church {
    void registerParishioner(Parishioner parishioner);
    void removeParishioner(Parishioner parishioner);
    void notifyParishioners();
}
Mayroong isang partikular na Simbahang Katoliko na may pagpapatupad ng mga pamamaraang ito, pati na rin ang mga balita at isang listahan ng mga tao kung kanino dapat i-broadcast ang balitang ito:
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);
    }
}
May isang parokyano na pwedeng pumasok o lumabas ng simbahan (para mapasimple ang code, papayagan lang namin siyang makapasok :)
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);
    }
}
Alinsunod dito, ito ay kung paano ito gagana:
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 года");
    }
}
at ang resulta ng programa:
Мартин Лютер узнал новость: Инквизиция была ошибкой... месса Mea Culpa 12 марта 2000 года
Жан Кальвин узнал новость: Инквизиция была ошибкой... месса Mea Culpa 12 марта 2000 года
Yung. Sa sandaling lumitaw ang balita sa simbahan, ang lahat na nasa hanay ng mga rehistradong miyembro ng simbahang ito ay aabisuhan tungkol dito. Ano ang mga disadvantage ng pagpapatupad na ito: 1. Una, ang interface kung saan maaari kang magparehistro at tumanggap ng mga balita ay maaaring hindi lamang ang simbahang ito (maaaring kailanganin ito). Samakatuwid, magiging posible na agad itong ilipat sa isang hiwalay na Observable interface. 2. Ang parehong ay maaaring gawin sa mga parishioner ng simbahan, ibig sabihin, ilipat ang paraan ng pag-update sa isang hiwalay na interface at ipatupad ito para sa nais na parishioner. Kung gayon ang pamamaraang ito ay magagamit sa pangkalahatan hindi ng mga parokyano ng Simbahang Katoliko, ngunit, halimbawa, ng mga naninirahan sa pagkakaroon ng mga duwende (ibig sabihin ang kilusang "Daan patungo sa Unicorn"). Yung. lumikha ng interface ng Observer na may paraan ng pag-update. Ano ang mangyayari sa huli:
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);
    }
}
Таким образом: Мы «ослабor связь» между церковью и прихожанами, что естественно хорошо только в программировании :) Субъект (католическая церковь) имеет лишь список слушателей (прихожан) и при получении новостей (изменений), транслирует данные новости своим слушателям. Можно завести теперь любой другой субъект (например протестанскую церковь) и там уже транслировать новости «своим» слушателям. Также нужно учесть, что данные 2 класса (точнее класс Observable и интерфейс Observer) имелись в пакете java.util java, но сейчас они Deprecation с java 9 (https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/util/Observable.html): Deprecated. This class and the Observer interface have been deprecated. The event model supported by Observer and Observable is quite limited, the order of notifications delivered by Observable is unspecified, and state changes are not in one-for-one correspondence with notifications. For a richer event model, consider using the java.beans package. For reliable and ordered messaging among threads, consider using one of the concurrent data structures in the java.util.concurrent package. For reactive streams style programming, see the Flow API. Поэтому использовать их не нужно. А instead of них можно использовать другие, но суть паттерна от этого не изменится. Для примера давайте попробует использовать PropertyChangeListener (чтобы не писать лишние классы, которые уже написаны) из пакета java.beans. Давайте посмотрим How это будет: класс субъекта:
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;
    }
}
и класс слушателя:
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);
    }
}
Если мы выполним следующий code:
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 год");
}
Получим следующий результат:
Мартин Лютер узнал новость: Дева Мария имеет непорочное зачатие... булла Ineffabilis Deus... 8 декабря 1854 года Папа Пий IX Жан Кальвин узнал новость: Дева Мария имеет непорочное зачатие... булла Ineffabilis Deus... 8 декабря 1854 года Папа Пий IX Мартин Лютер узнал новость: Папа непогрешим... не всегда конечно, а только когда транслирует учение церкви ex cathedra... Первый Ватиканский собор 1869 год Жан Кальвин узнал новость: Папа непогрешим... не всегда конечно, а только когда транслирует учение церкви ex cathedra... Первый Ватиканский собор 1869 год
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION