Паттерн «Наблюдатель»

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

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

Введение

назначение

Он создаёт отношение зависимости «один ко многим» между объектами. Когда состояние одного объекта изменяется, все зависящие от него объекты получают уведомление и автоматически обновляются.

Основная решаемая проблема

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

Сценарий использования

  • Когда изменение состояния одного объекта требует одновременного обновления других объектов.

Подход к реализации

  • Определите интерфейс наблюдателя: Содержит метод update.
  • Создайте конкретных наблюдателейРеализует интерфейс наблюдателя и определяет поведение при получении уведомления.
  • Определите интерфейс субъектаСодержит методы добавления, удаления и уведомления наблюдателей.
  • Создайте конкретный субъект: Реализуйте интерфейс субъекта, управляйте списком наблюдателей и уведомляйте наблюдателей при изменении состояния.

Ключевой код

  • Список наблюдателей: Поддерживайте список наблюдателей в субъекте.

Пример приложения

  • Аукционная система: Аукционист выступает в роли субъекта, участники торгов выступают в роли наблюдателей, и все участники торгов получают уведомление при обновлении цены аукциона.
  • История «Путешествие на Запад»Бодхисаттва, окропляющая воду, служит изменением состояния, а старая черепаха выступает наблюдателем, наблюдающим это изменение.

Преимущества

  • Абстрактная связанность: между наблюдателями и субъектом существует абстрактная связь.
  • Механизм запускаУстанавливает механизм запуска и уведомления для изменений состояния.

Недостатки

  • Проблемы производительностиЕсли наблюдателей много, процесс уведомления может занимать много времени.
  • Циклическая зависимостьМожет приводить к циклическим вызовам и сбоям системы.
  • Отсутствие деталей изменения: наблюдатели не знают, как изменяется субъект, а лишь то, что изменение произошло.

Рекомендации по использованию

  • Используйте его, когда нужно уменьшить связанность между объектами и когда изменения состояния объекта должны вызывать изменения других объектов.
  • Рассмотрите возможность использования встроенных в Java классов поддержки паттерна «Наблюдатель», таких какjava.util.Observableиjava.util.Observer。

Примечания

  • Избегайте циклических ссылок: будьте осторожны с зависимостью между наблюдателями и субъектом, чтобы избежать циклических ссылок.
  • Асинхронное выполнениеРассмотрите возможность использования асинхронного уведомления, чтобы избежать ситуации, когда единая точка отказа приводит к остановке всей системы.

Структура

Паттерн «Наблюдатель» включает следующие основные роли:

  • Субъект: Также известен как наблюдаемый (observed или observable), это объект с состоянием, который поддерживает список наблюдателей. Субъект предоставляет методы для добавления, удаления и уведомления наблюдателей.
  • Наблюдатель: Наблюдатель — это объект, который получает уведомления от субъекта. Он должен реализовать метод update, который вызывается для выполнения операций обновления при получении уведомления от субъекта.
  • Конкретный субъект: Конкретный субъект — это конкретный класс реализации субъекта. Он поддерживает список наблюдателей и уведомляет наблюдателей при изменении состояния.
  • Конкретный наблюдатель: Конкретный наблюдатель — это конкретный класс реализации наблюдателя. Он реализует метод update и определяет конкретные операции, которые нужно выполнять при получении уведомления от субъекта.

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

Реализация

Паттерн «Наблюдатель» использует три класса: Subject, Observer и Client. Объект Subject имеет методы для привязки наблюдателей к объекту Client и отвязки наблюдателей от объекта Client. Мы создаёмSubjectкласс,Observerабстрактный класс и классы, расширяющие абстрактный классObserverкласс сущности.

ObserverPatternDemo, наш демонстрационный класс используетSubjectи объекты классов сущностей для демонстрации паттерна «Наблюдатель».

观察者模式的 UML 图

Шаг 1

Создайте класс Subject.

Subject.java

import java.util.ArrayList; import java.util.List; public class Subject { private List<Observer> observers = new ArrayList<Observer>(); private int state; public int getState() { return state; } public void setState(int state) { this.state = state; notifyAllObservers(); } public void attach(Observer observer){ observers.add(observer); } public void notifyAllObservers(){ for (Observer observer : observers) { observer.update(); } } }

Шаг 2

Создайте класс Observer.

Observer.java

public abstract class Observer { protected Subject subject; public abstract void update(); }

Шаг 3

для создания классов наблюдателей сущностей.

BinaryObserver.java

public class BinaryObserver extends Observer{ public BinaryObserver(Subject subject){ this.subject = subject; this.subject.attach(this); } @Override public void update() { System.out.println( "Binary String: " + Integer.toBinaryString( subject.getState() ) ); } }

OctalObserver.java

public class OctalObserver extends Observer{ public OctalObserver(Subject subject){ this.subject = subject; this.subject.attach(this); } @Override public void update() { System.out.println( "Восьмеричная строка: " + Integer.toOctalString( subject.getState() ) ); } }

HexaObserver.java

public class HexaObserver extends Observer{ public HexaObserver(Subject subject){ this.subject = subject; this.subject.attach(this); } @Override public void update() { System.out.println( "Шестнадцатеричная строка: " + Integer.toHexString( subject.getState() ).toUpperCase() ); } }

Шаг 4

ИспользованиеSubjectи объекты-наблюдатели сущности.

ObserverPatternDemo.java

public class ObserverPatternDemo { public static void main(String[] args) { Subject subject = new Subject(); new HexaObserver(subject); new OctalObserver(subject); new BinaryObserver(subject); System.out.println("Первое изменение состояния: 15"); subject.setState(15); System.out.println("Второе изменение состояния: 10"); subject.setState(10); } }

Шаг 5

Запустите программу и выведите результаты:

First state change: 15
Hex String: F
Octal String: 17
Binary String: 1111
Second state change: 10
Hex String: A
Octal String: 12
Binary String: 1010
Другие расширения