JavaRush /Java блогу /Random-KY /Байкоочу үлгүсү

Байкоочу үлгүсү

Группада жарыяланган
The Gang of Four жазгандай (4 мыкты иштеп чыгуучунун "Объектке багытталган дизайн үлгүлөрү" китебине шилтеме кылуу менен), бул үлгүнүн максаты an objectтердин ортосундагы бирден көпкө көз карандылыкты аныктоо болуп саналат. бир an objectтин абалы өзгөрсө, ага көз каранды болгондордун бардыгы бул тууралуу кабарланат жана автоматтык түрдө жаңыртылып турат. Бул үлгү дагы деп аталат: Көз карандылар (баш ийгендер) же Жарыялоо-жазылуу (жарыялоочу - жазылуучу). Бирок, келгиле, аны католик чиркөөсүнүн мисалында түшүнүүгө аракет кылалы :) Бул чиркөөнүн окууларына ишенген жолдоочулары бар. Кандайдыр бир жаңы догмалар (милдеттүү ишенимдер) жана башкалар пайда болгондо, бул адамдар алар жөнүндө бorши керек. Бирок бул үлгүнү колдонуу менен программалоо тorнде муну кантип сүрөттөсө болот? 1. Бизде «чиркөөнүн үнү» (чиркөөнүн өзү же экс-кафедраны уктурууда Папа), башкача айтканда, чиркөөдөгү жаңылыктарды жарыялаган белгилүү бир уктуруучу же субъект бар. 2. Бул чиркөөнүн паришионерлери, башкача айтканда, маанилүү окуялардан кабардар болгусу келген кээ бир байкоочулар бар. Ошого жараша бүгүн 1,3 миллиард паришионер болушу мүмкүн, эртең аздыр-көптүр болушу мүмкүн. Жана сиз бул чиркөөдөгүлөргө гана кабарлашыңыз керек (кайра атеисттерди убара кылуунун кереги жок :). Ошентип, мунун бардыгын төмөнкүчө чагылдырууга болот: бир чиркөө бар, ал өз үйүрүн бир нерсе жөнүндө айтып берет, анда сиз каттоодон өтсөңүз болот же тескерисинче, андан чыгып кете аласыз:
public interface Church {
    void registerParishioner(Parishioner parishioner);
    void removeParishioner(Parishioner parishioner);
    void notifyParishioners();
}
Бул ыкмаларды ишке ашыруу менен белгилүү бир католик чиркөөсү бар, ошондой эле кабар жана бул кабар уктуруу керек адамдардын тизмеси:
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);
    }
}
Чиркөөгө кирип же чыга турган чиркөө бар (codeду жөнөкөйлөтүү үчүн биз ага кирүүгө гана уруксат беребиз :)
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);
    }
}
Демек, бул кандай иштейт:
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 года");
    }
}
жана программанын натыйжасы:
Мартин Лютер узнал новость: Инквизиция была ошибкой... месса Mea Culpa 12 марта 2000 года
Жан Кальвин узнал новость: Инквизиция была ошибкой... месса Mea Culpa 12 марта 2000 года
Ошол. Чиркөөдө жаңылык пайда болоору менен, бул чиркөөнүн катталган мүчөлөрүнүн катарына киргендердин бардыгына бул тууралуу кабар берилет. Бул ишке ашыруунун кемчorктери эмнеде ? Ошондуктан, аны дароо өзүнчө Байкоочу интерфейске жылдыруу мүмкүн болмок. 2. Ушундай эле нерсени чиркөө чиркөөчүлөрү менен да жасаса болот, тактап айтканда, жаңыртуу ыкмасын өзүнчө интерфейске жылдырып, аны каалаган чиркөөчү үчүн ишке ашырыңыз. Ошондо бул ыкманы жалпысынан католик чиркөөсүнүн чиркөөчүлөрү эмес, мисалы, эльфтердин ("Бир мүйүздүү мүйүзгө жол" кыймылы дегенди билдирет) жашагандар колдоно алышат. Ошол. жаңыртуу ыкмасы менен Observer интерфейсин түзүү. Акыры эмне болот:
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);
    }
}
Ошентип: Биз чиркөө менен чиркөөчүлөрдүн ортосундагы "байланышты начарлаттык", бул табигый түрдө программалоодо гана жакшы :) Субъект (католик чиркөөсү) угуучулардын (чиркөөлөрдүн) тизмеси гана бар жана жаңылыктарды (өзгөртүүлөрдү) алганда, бул жаңылыкты таратат. анын угуучуларына. Эми сиз каалаган башка уюмду түзө аласыз (мисалы, протестанттык чиркөө) жана жаңылыктарды "сиздин" угуучуларыңызга тарата аласыз. Ошондой эле 2-класстын маалыматтары (тактап айтканда, Байкоочу класс жана Байкоочу интерфейси) java.util java пакетинде жеткorктүү болгонун, бирок азыр алар java 9 (https://docs.oracle. com/en/java/javase/15/ docs/api/java.base/java/util/Observable.html): Эскирген. Бул класс жана Observer интерфейси жокко чыгарылган. Observer жана Observable тарабынан колдоого алынган окуя модели кыйла чектелген, Байкоочу тарабынан жеткирилген эскертмелердин тартиби такталбаган жана абалдын өзгөртүүлөрү билдирмелер менен бирден-бир кат алышууда эмес. Окуянын көбүрөөк модели үчүн java.beans пакетин колдонууну карап көрүңүз. Жиптер арасында ишенимдүү жана иреттүү билдирүү алыш үчүн, java.util.concurrent топтомундагы параллелдүү маалымат структураларынын бирин колдонууну карап көрүңүз. Реактивдүү агымдардын стorн программалоо үчүн Flow API караңыз. Ошондуктан аларды колдонуунун кереги жок. Анын ордуна башкаларды колдонсоңуз болот, бирок үлгүнүн маңызы өзгөрбөйт. Мисалы, java.beans пакетинен PropertyChangeListener (буга чейин жазылган кошумча класстарды жазбаш үчүн) колдонуп көрөлү. Бул кандай болорун карап көрөлү: предметтик класс:
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 год");
}
Биз төмөнкү натыйжаны алабыз:
Мартин Лютер кабарды билди: Бүбү Мариям кемчorксиз боюнда болгон... бука Инеффабorс Деус... 1854-жылдын 8-декабрында Папа Пиус IX Джон Кальвин кабарды билди: Бүбү Мариям кемчorксиз төрөттөн... Бука Ineffabilis Deus ... 1854-жылдын 8-декабрында Папа Пиус IX Мартин Лютер мындай жаңылыкты билди: Папа жаңылбас... албетте, ар дайым эмес, бирок ал чиркөөнүн экс-кафедрасынын окууларын бергенде гана... Биринчи Ватикан Кеңеши 1869-ж. Джон Кальвин үйрөнгөн. жаңылык: Папа жаңылбас... албетте, ар дайым эмес, бирок ал чиркөөнүн экс-кафедрасынын окуусун бергенде гана... Биринчи Ватикан Кеңеши 1869-ж.
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION