Шаблон наблюдателя против шаблона публикации-подписки, больше не путайте

внешний интерфейс Шаблоны проектирования JavaScript
Шаблон наблюдателя против шаблона публикации-подписки, больше не путайте

«Это второй день моего участия в первом испытании обновлений 2022 года. Подробную информацию о мероприятии см.:Вызов первого обновления 2022 г."

предисловие

Режим наблюдения и режим публикации-подписки — часто используемые режимы в повседневной разработке, и небольшие пакеты не смогли их хорошо различить.Несколько дней назад я слушал почерк.promiseПри создании исходного кода учитель подробно объяснил два режима и обнаружил, что мне все еще сложно его понять.

Лучше поймать раннее, чтобы поймать слишком умные, совсем недавно пакеты, использующие интерпретацию стиля боевых искусств.JavaScript, мир боевых искусств действительно может датьJavaScriptДругое очарование, давайте посмотрим, как Сяобао использует боевые искусства для понимания шаблонов проектирования, и приложим несколько реальных случаев, которые помогут вам полностью понять шаблон наблюдения и шаблон публикации-подписки.

предыстория истории

С тех пор, как передовая секта выпустила план наследования, секта становилась все более и более процветающей, а уровень учеников постоянно повышался, но появилась новая проблема - качественных заданий серьезно не хватает. Пятизвездочные задания, выпускаемые Миссионерским залом Цзунмэнь каждый месяц, ограничены, и ученики, которые хотят получить пятизвездочные задания, подобны карасям, переплывающим реку, поэтому они размножаютсяСкальпер боевых искусств, злобно хватайтесь за задание, садитесь на землю и запускайте цену.

Zongmen не хотел, чтобы задание было злонамеренно разграблено, и решил скорректировать порядок рынка заданий, поэтому запустил функцию подписки на задание — режим наблюдателя.

Шаблон наблюдателя

Общая функция подписки на задание заключается в следующем: Цзунмэнь запустил функцию пятизвездочной подписки на задание, и ученики получают права на подписку через покупку.Когда Цзунмэнь публикует пятизвездочные задания, он уведомляет учеников, у которых есть права на подписку.

Тогда в функции подписки на задачи есть два типа субъектов:

  • Миссионерский зал Цзунмэнь
    • Ведение списка учеников с правом подписки
    • Предоставляет ученикам возможность приобретать права на подписку
    • Уведомлять учеников с правами подписки после публикации соответствующей задачи
  • Уведомление о принятии задачи учеников

Отношения между миссионерским залом секты и вышестоящими учениками фактически представляют собой режим наблюдателя.

Так что же такое шаблон наблюдателя?Когда между объектами существует зависимость «один ко многим», состояние одного из объектов изменяется, и все объекты, которые зависят от него, будут уведомлены.Это шаблон наблюдателя.

В шаблоне наблюдателя есть только два типа агентов: целевой объект (Object) и наблюдатель (Observer). Зал SECT Mission - это цель, и ученики являются наблюдателями.

  • цельSubject:
    • Ведение списка наблюдателейobserverList——— Ведение списка учеников с правом подписки
    • Определить способ добавления наблюдателей — Предусмотреть функцию учеников для покупки прав на подписку
    • Когда он изменяется, вызывая собственныйnotifyМетод, в свою очередь, уведомляет каждого наблюдателя о выполненииupdateМетод — — Уведомить учеников с разрешением на подписку после публикации соответствующей задачи.
  • наблюдательObserverнеобходимо реализоватьupdateметод для вызова целевого объекта.updateПользовательская бизнес-логика может быть выполнена в методе — ученикам необходимо определить метод после получения уведомления о задаче, например, захват задачи или задача не подходит, продолжайте ждать следующей задачи

Давайте визуализируем текст выше:

Observer.png

class Observer {
    constructor(name) {
        this.name = name;
    }
    update({taskType, taskInfo}) {
        // 假设任务分为日常route和战斗war
        if (taskType === "route") {
            console.log(`${this.name}不需要日常任务`);
            return;
        }
        this.goToTaskHome(taskInfo);
        
    }
    goToTaskHome(info) {
        console.log(`${this.name}去任务大殿抢${info}任务`);
    }
}

class Subject {
    constructor() {
        this.observerList = []
    }
    addObserver(observer) {
        this.observerList.push(observer);
    }
    notify(task) {
        console.log("发布五星任务");
        this.observerList.forEach(observer => observer.update(task))
    }
}

const subject = new Subject();
const stu1 = new Observer("弟子1");
const stu2 = new Observer("弟子2");

// stu1 stu2 购买五星任务通知权限
subject.addObserver(stu1);
subject.addObserver(stu2);

// 任务殿发布五星战斗任务
const warTask = {
    taskType: 'war',
    taskInfo: "猎杀时刻"
}

// 任务大殿通知购买权限弟子
subject.notify(warTask);

// 任务殿发布五星日常任务
const routeTask = {
    taskType: 'route',
    taskInfo: "种树浇水"
}

subject.notify(routeTask);

Выходной результат:

// 战斗任务
发布五星任务
弟子1去任务大殿抢猎杀时刻任务
弟子2去任务大殿抢猎杀时刻任务

// 日常任务
发布五星任务
弟子1不需要日常任务
弟子2不需要日常任务

Из приведенного выше кода видно, что когда секта публикует задание, подписавшиеся ученики (наблюдатели) получат самое последнее уведомление о задании.

Видя это, я не знаю, можете ли вы понять шаблон наблюдателя?

Позвольте мне дать вам еще один каштан: Например, вы хотите подать заявку на должность фронтенд-инженера в Alibaba, но HR-служба Alibaba сообщает вам, что вакансий больше нет, оставьте свой номер телефона и подождите, пока с вами свяжутся. Итак, вы с радостью оставили контактную информацию. Как всем известно, HR оставил много контактной информации. К счастью, 30 февраля 2022 года в Alibaba была должность инженера по интерфейсу, и отдел кадров связался с оставленной контактной информацией.

В случае, Alibaba является цельюSubject, список контактов используется для ведения наблюдателяobserverList, вызываемый по наличию или отсутствию внешних позицийnotifyметод.

модель публикации-подписки

Так что же такое модель публикации-подписки?Объекты, которые хотят получать уведомления на основе канала события (темы)SubscriberПодписка на тему через пользовательское событие, объект активированного событияPublisherУведомить каждого, кто подписался на тему, опубликовав события темыSubscriberобъект.

Таким образом, по сравнению с режимом наблюдателя, режим публикации-подписки имеет три роли: издательPublisher, Центр диспетчерского событияEvent Channel,подписчикSubscriber.

Вышеприведенный текст немного сложен для понимания.Мы продолжаем воспринимать задание ученика как каштан.Цунмэнь считает, что размещать подписку на задание в зале заданий немного громоздко,поэтому мы решили добавить его между заданием зал и ученик.посредник. Ученики подписываются на нужный им тип задания в посреднике.Когда зал заданий опубликует задание, посредник опубликует задание соответствующим подписчикам.

  • Миссионерский зал Цзунмэнь: Издатель миссий ——Publisher
  • Функция посредничества-Event Channel
    • Типы задач обслуживания и подписки для каждой задачи
    • Предоставьте подписчикам функции подписки --subscribeФункция
    • Когда секта опубликует задачу, посредник опубликует задачу всем подписчикам——publishФункция
  • Ученик: Получатель задания ——Subscriber

publish-subscribe.png

Позвольте мне привести вам еще один пример: с текущимНачало популярной драмыНапример, когда приближается китайский Новый год, мысли о рыбалке становятся все тяжелее и тяжелее.Каждый день я не могу дождаться начала обновления, и я хочу начать смотреть драму в первый момент обновления. , так что ты будешь делать? Вы не можете постоянно обновлять страницу. Платформа предоставляет функцию подписки на сообщения.Если вы решите подписаться, после запуска обновления платформы она отправит сообщение, чтобы уведомить вас как можно скорее.После подписки вы можете с радостью следить за драмой.

В приведенном выше случае начало — это издатель.Publisher, подписчик это подписчикSubscribe, платформа предполагает канал событийEvent ChannelФункция.

class PubSub {
    constructor() {
        // 事件中心
        // 存储格式: warTask: [], routeTask: []
        // 每种事件(任务)下存放其订阅者的回调函数
        this.events = {}
    }
    // 订阅方法
    subscribe(type, cb) {
        if (!this.events[type]) {
            this.events[type] = [];
        }
        this.events[type].push(cb);
    }
    // 发布方法
    publish(type, ...args) {
        if (this.events[type]) {
            this.events[type].forEach(cb => cb(...args))
        }
    }
    // 取消订阅方法
    unsubscribe(type, cb) {
        if (this.events[type]) {
            const cbIndex = this.events[type].findIndex(e=> e === cb)
            if (cbIndex != -1) {
                this.events[type].splice(cbIndex, 1);
            }
        }
        if (this.events[type].length === 0) {
            delete this.events[type];
        }
    }
    unsubscribeAll(type) {
        if (this.events[type]) {
            delete this.events[type];
        }
    }
}

// 创建一个中介公司
let pubsub = new PubSub();

// 弟子一订阅战斗任务
pubsub.subscribe('warTask', function (taskInfo){
    console.log("宗门殿发布战斗任务,任务信息:" + taskInfo);
})
// 弟子一订阅战斗任务
pubsub.subscribe('routeTask', function (taskInfo) {
    console.log("宗门殿发布日常任务,任务信息:" + taskInfo);
});
// 弟子三订阅全类型任务
pubsub.subscribe('allTask', function (taskInfo) {
    console.log("宗门殿发布五星任务,任务信息:" + taskInfo);
});

// 发布战斗任务
pubsub.publish('warTask', "猎杀时刻");
pubsub.publish('allTask', "猎杀时刻");

// 发布日常任务
pubsub.publish('routeTask', "种树浇水");
pubsub.publish('allTask', "种树浇水");

Выходной результат:

// 战斗任务
宗门殿发布战斗任务,任务信息:猎杀时刻
宗门殿发布五星任务,任务信息:猎杀时刻
// 日常任务
宗门殿发布日常任务,任务信息:种树浇水
宗门殿发布五星任务,任务信息:种树浇水

Выводя результаты, мы можем обнаружить, что издатель и подписчик не знают о существовании друг друга. Требуется сторонний посредник, соединяющий подписчиков и издателей в тандеме, используя посредника для фильтрации и распространения всех входящих сообщений. То есть,Модель публикации-подписки используется для управления обменом информацией между различными компонентами системы, даже если эти компоненты не знают о существовании друг друга..

Суммировать

Шаблон наблюдателя и шаблон публикации-подписки были упомянуты выше, давайте суммируем различия между ними:

observer-publish_subscribe.png

Шаблоны проектирования Шаблон наблюдателя модель публикации-подписки
основной корпус Наблюдатель объекта, целевой объект субъекта Издатель-издатель, центр событий Event Channel, подписчик подписки
предмет отношения Запись ObServer через ObserverList в тему Издатель и Подписчик не хотят знать друг друга и связываются через посредников
преимущество Роль ясна, Субъект и Объект должны следовать согласованным методам участников. Слабосвязанная, высокая гибкость, обычно используется в асинхронном программировании.
недостаток тесно связаны Чем больше типов событий, тем больше стоимость обслуживания.
Случаи применения двусторонняя привязка данных Event Bus Eventbus

Горячая текстовая рекомендация

Недавние события

Серия JavaScript для продвинутых пользователей

часть интервью

счастливое программирование

Ссылка на ссылку

послесловие

Друзья, если вы чувствуете, что эта статья вам полезна, ставьте лайк Абао👍 или подписывайтесь➕ — это самая большая поддержка для меня.

Кроме того, если есть какие-либо проблемы с этой статьей или если вы не понимаете часть статьи, вы можете ответить мне в области комментариев, давайте обсудим, изучим и добьемся успеха вместе!

Эпидемия скоро закончится, и мир вернется к миру