JavaRush /وبلاگ جاوا /Random-FA /الگوی مشاهده گر

الگوی مشاهده گر

در گروه منتشر شد
همانطور که گروه چهار می نویسد (با اشاره به کتاب "الگوهای طراحی شی گرا" توسط 4 توسعه دهنده درجه یک)، هدف از این الگو این است که یک وابستگی یک به چند را بین اشیا تعریف کند به گونه ای که وقتی وضعیت یک شی تغییر می کند، همه افراد وابسته به آن از این موضوع مطلع می شوند و به طور خودکار به روز می شوند. این الگو همچنین نامیده می شود: وابسته (فرع) یا Publish-Subscribe (ناشر - مشترک). اما بیایید سعی کنیم آن را با استفاده از نمونه کلیسای کاتولیک کشف کنیم :) این کلیسا پیروانی دارد که به آموزه های این کلیسا اعتقاد دارند. وقتی هر دگم جدید (اعتقادات واجب) و بیشتر ظاهر می شود، این افراد باید در مورد آنها بدانند. اما چگونه می توان این را در یک زبان برنامه نویسی با استفاده از این الگو توصیف کرد؟ 1. ما "صدای کلیسا" را داریم (خود کلیسا یا پاپ هنگام پخش ex cathedra)، یعنی یک پخش کننده یا سوژه خاص که اخبار را در کلیسا اعلام می کند. 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);
    }
}
یک عضو کلیسا وجود دارد که می تواند وارد کلیسا شود یا از آن خارج شود (برای ساده کردن کد، فقط به او اجازه ورود می دهیم :)
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 года
آن ها به محض ظاهر شدن اخبار در کلیسا، همه کسانی که در آرایه اعضای ثبت نام شده این کلیسا هستند، از آن مطلع خواهند شد. معایب این پیاده سازی چیست: 1. اولاً، رابطی که می توانید در آن ثبت نام کنید و اخبار دریافت کنید ممکن است نه تنها به این کلیسا مربوط باشد (این ممکن است لازم باشد). بنابراین، می توان فوراً این را به یک رابط قابل مشاهده جداگانه منتقل کرد. 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 (به طور دقیق تر، کلاس Observable و رابط Observer) در بسته جاوا java.util موجود بودند، اما اکنون آنها Deprecation با جاوا 9 (https://docs.oracle) هستند. com/en/java/javase/15/ docs/api/java.base/java/util/Observable.html): منسوخ شده است. این کلاس و رابط Observer منسوخ شده اند. مدل رویدادی که توسط Observer و Observable پشتیبانی می‌شود کاملاً محدود است، ترتیب اعلان‌های ارائه‌شده توسط Observable نامشخص است، و تغییرات حالت مطابقت یک به یک با اعلان‌ها نیست. برای یک مدل رویداد غنی تر، از بسته java.beans استفاده کنید. برای پیام رسانی مطمئن و منظم در بین رشته ها، استفاده از یکی از ساختارهای داده همزمان در بسته java.util.concurrent را در نظر بگیرید. برای برنامه‌نویسی سبک جریان‌های واکنشی، Flow API را ببینید. بنابراین نیازی به استفاده از آنها نیست. و به جای آن می توانید از دیگران استفاده کنید، اما ماهیت الگو تغییر نخواهد کرد. به عنوان مثال، بیایید سعی کنیم از PropertyChangeListener (برای اینکه کلاس های غیر ضروری که قبلا نوشته شده اند ننویسیم) از بسته java.beans استفاده کنیم. بیایید ببینیم چگونه خواهد بود: class class:
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);
    }
}
اگر کد زیر را اجرا کنیم:
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 پاپ پیوس نهم جان کالوین این خبر را دریافت: مریم باکره از لقاح معصوم است... Bull Ineffabilis Deus ... 8 دسامبر 1854 پاپ پیوس نهم مارتین لوتر این خبر را دریافت: پاپ خطاناپذیر است... البته نه همیشه، بلکه فقط زمانی که آموزه های کلیسای ex cathedra را پخش می کند... اولین شورای واتیکان 1869 جان کالوین یاد گرفت. اخبار: پاپ خطاناپذیر است... البته نه همیشه، بلکه فقط زمانی که تدریس کلیسای سابق را پخش می کند... اولین شورای واتیکان 1869
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION