Интервью с Ali P6+: представляем режим наблюдателя?

интервью Java
Интервью с Ali P6+: представляем режим наблюдателя?

Есть чувства, есть галантерейные товары, поиск в WeChat【Третий принц Ао Бин] Подпишитесь на этого программиста, у которого есть кое-что.

эта статьяGitHub github.com/JavaFamilyВключено, и есть полные тестовые площадки, материалы и мой цикл статей для интервью с производителями первой линии.

Очередь сообщений (MQ), модель связи, которая может реализовать одностороннюю связь между производителями и потребителями, также является широко используемым сегодня промежуточным программным обеспечением. Есть RabbitMQ, ActiveMQ, Kafka и т. д. У них много функций, таких какразъединение,асинхронный,транслировать,отсечение пикаи многие другие преимущества.

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

Сегодня A Bing будет использовать этот режим, который более распространен в реальных разработках.

контур

определение

Что такое шаблон наблюдателя? Какова его цель?

Когда состояние объекта изменяется, другие зарегистрированные объекты могут наблюдать за изменением и вносить соответствующие изменения. Таким образом можно добиться эффекта уменьшения зависимостей и развязки.

Например, это похоже на WeChat Moments, где текущий человек является подписчиком, а друзья — темой. Когда человек публикует динамический круг друзей, его друзья могут видеть этот круг друзей и могут ставить лайки или комментировать свои собственные.

Это кажется немного абстрактным, давайте посмотрим на его главные роли:

  • Субъект (subject): наблюдаемый интерфейс, в основном реализуемый классом, уведомляющий наблюдателя о необходимости использования метода присоединения и метода отсоединения об отмене наблюдения.
  • ConcreteSubject: класс, который реализует интерфейс субъекта и обрабатывает изменения в наблюдателях.
  • Observe (Наблюдатель): Observer — это интерфейс, политый объектом, который обновляется на основе изменений субъекта.

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

public interface Subject {
    // 添加订阅关系
    void attach(Observer observer);
    // 移除订阅关系
    void detach(Observer observer);
    // 通知订阅者
    void notifyObservers(String message);
}

Сначала создайте определение темы, определите отношения добавления и удаления и уведомите подписчиков.

public class ConcreteSubject implements Subject {

    // 订阅者容器
    private List<Observer> observers = new ArrayList<Observer>();

    @Override
    public void attach(Observer observer) {
        // 添加订阅关系
        observers.add(observer);
    }

    @Override
    public void detach(Observer observer) {
        // 移除订阅关系
        observers.remove(observer);
    }

    @Override
    public void notifyObservers(String message) {
        // 通知订阅者们
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

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

public interface Observer {
    // 处理业务逻辑
    void update(String message);
}

Создадим интерфейс наблюдателя, которым нам удобно управлять

public class FriendOneObserver implements Observer {
   
  @Override
    public void update(String message) {
        // 模拟处理业务逻辑
        System.out.println("FriendOne 知道了你发动态了" + message);
    }
}

Наконец, создайте определенный класс наблюдателя, реализуйте метод обновления интерфейса наблюдателя и обработайте его собственную бизнес-логику.

public class test {
    
    public static void main(String[] args) {

        ConcreteSubject subject = new ConcreteSubject();
        // 这里假设是添加好友
        subject.attach(new FriendOneObserver());
        FriendTwoObserver twoObserver = new FriendTwoObserver();
        subject.attach(twoObserver);

        // 发送朋友圈动态
        subject.notifyObservers("第一个朋友圈消息");
        // 输出结果: FriendOne 知道了你发动态了第一个朋友圈消息
        //          FriendTwo 知道了你发动态了第一个朋友圈消息

        // 这里发现 twoObserver 是个推荐卖茶叶的,删除好友
        subject.detach(twoObserver);
        subject.notifyObservers("第二个朋友圈消息");
        // 输出结果:FriendOne 知道了你发动态了第二个朋友圈消息
    }
}

Последнее, что нужно посмотреть на результаты теста.Отношения подписки поддерживаются через ConcreteSubject.После уведомления подписчиков с помощью метода notifyObservers, наблюдатели получают сообщение для обработки своей собственной бизнес-логики.

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

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

Это просто синхронная реализация, мы также можем расширить другие асинхронные реализации или использовать многопоточность и другие реализации.

рамочное приложение

Применение паттерна Observer во фреймворке тоже должно быть много

  • Первый тип людей, знакомых с JDK, должен знать, что в дополнение к обычно используемым коллекциям и картам в пакете java.util есть такжеObservableКласс, его реализация на самом деле является шаблоном наблюдателя. это такжедобавить, удалить, уведомитьи другие методы.

    Здесь следует отметить, что он использует Vector в качестве контейнера для отношения подписки и в то же время добавляет ключевое слово synchronized в свой метод определения, чтобы изменить класс для достижения потокобезопасности.

    Здесь я разместил исходный код ключа, а заинтересованные студенты могут сами открыть и посмотреть комментарии к каждому методу.

  • Второй — это ApplicationListener в Spring, который также обрабатывается режимом наблюдателя, ApplicationEventMulticaster используется как тема, которая включает в себя добавление, удаление, уведомление и т. д.

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

import java.util.EventListener;

/**
 * Interface to be implemented by application event listeners.
 * Based on the standard {@code java.util.EventListener} interface
 *  for the Observer design pattern. // 这里也已经说明是采用观察者模式
 *
 * <p>As of Spring 3.0, an ApplicationListener can generically declare the event type
 * that it is interested in. When registered with a Spring ApplicationContext, events
 * will be filtered accordingly, with the listener getting invoked for matching event
 * objects only.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @param <E> the specific ApplicationEvent subclass to listen to
 * @see org.springframework.context.event.ApplicationEventMulticaster //主题
 */
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	/**
	 * Handle an application event.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}
  • Третий механизм обработки событий Google GuavaGuava EventBusЕго реализация также использует шаблон проектирования наблюдателя в шаблоне проектирования.

    В настоящее время EventBus реализован двумя способами:

    • EventBus // Режим синхронной блокировки
    • AsyncEventBus // // Асинхронный неблокирующий режим

EventBus также предоставляет ряд методов для нашего удобства:

  • зарегистрировать метод как добавить наблюдателя

  • Метод unregister удаляет наблюдателя

  • Метод post отправляет уведомления и т. д.

Это очень удобно в использовании. Вы можете создать подписчика, добавив аннотацию @Subscribe, подробнее о том, как ее использовать, смотрите на официальном сайте.

Примеры реальной трансформации бизнеса

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

После успешной регистрации нового пользователя нам нужно сделать для него две вещи: первая — отправить сообщение об успешной регистрации, а вторая — отправить новому пользователю купон.

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

public class SendNewPersonCouponObserver implements Observer {

    ExecutorService pool = Executors.newFixedThreadPool(2);

    @Override
    public void update(String message) {

        Future<String> future = pool.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                TimeUnit.SECONDS.sleep(3);
                // 处理响应的业务逻辑
                return "调用发券服务,返回结果";
            }
        });
        try {
            // 假设等待200毫秒 没有获取到返回值结果则认为失败
            System.out.println(future.get(4000, TimeUnit.MILLISECONDS));
        } catch (Exception e) {
            // 执行异步获取失败
            // 记录日志,定时任务重试等
        }

        // 第一种不关心返回值结果
        Thread thread = new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                // 模拟服务调用 线程睡3秒钟
                TimeUnit.SECONDS.sleep(3);
                System.out.println("发送新人优惠券");
            }
        });
        thread.start();
        System.out.println("执行异步返回");
    }
}
public class SendSuccessMessageObserver implements Observer {

    @Override
    public void update(String message) {
        // 处理业务逻辑
        System.out.println("注册成功");
    }

    public static void main(String[] args) {
        // 假设用户注册成功直接通知观察者,改干自己的事情了
        ConcreteSubject subject = buildSubject();
        subject.notifyObservers("");
    }
 
   private static ConcreteSubject buildSubject() {
        ConcreteSubject subject = new ConcreteSubject();
        subject.attach(new SendSuccessMessageObserver());
        subject.attach(new SendNewPersonCouponObserver());
        return subject;
    }
}

Здесь мы написали два новых наблюдателя, в основном смотрящих на первый SendNewPersonCouponObserver, который асинхронно запускает новый поток для обработки нашей бизнес-логики.Когда нам нужно возвращаемое значение, мы можем использовать Future для получения возвращаемого результата.Чтобы преобразовать возвращаемое значение , вы можете напрямую открыть обычную нить.

Этот пример на самом деле относительно прост в целом, в основном для пояснения обработки асинхронных потоков.Конечно, его также можно реализовать с помощью Guava EventBus. И это не сложно, и заинтересованные друзья могут попробовать это сами.

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

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

Суммировать

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

Разумное использование шаблонов проектирования может сделать структуру кода более понятной, и в то же время оно также может отвечать единой ответственности различных небольших модулей, а также принципу «открыто-закрыто», чтобы достичь характеристик улучшения масштабируемости. код и низкие затраты на техническое обслуживание, как указано в предыдущем заводском шаблоне.

Я Ао Бин,Чем больше вы знаете, тем больше вы не знаете, спасибо за ваши таланты:как,собиратьиКомментарий, увидимся в следующий раз!


Статья постоянно обновляется, вы можете искать в WeChat "Третий принц Ао Бин"Прочтите это в первый раз, ответьте [материал] Подготовленные мной материалы интервью и шаблоны резюме крупных заводов первой линии, эта статьяGitHub github.com/JavaFamilyОн был включен, и есть полные тестовые сайты для интервью с крупными заводами.Добро пожаловать в Star.