Что такое шаблон проектирования Observer (Наблюдатель)?

«Что такое шаблон проектирования Observer (Наблюдатель)?» — вопрос из категории Паттерны, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Ключевые компоненты:

  • Subject (Субъект/Издатель): Содержит список наблюдателей и предоставляет методы для их добавления (attach), удаления (detach) и уведомления (notify).
  • Observer (Наблюдатель/Подписчик): Определяет интерфейс с методом обновления (например, update()), который вызывается субъектом.
  • ConcreteSubject & ConcreteObserver: Конкретные реализации.

Пример на Java:

// Интерфейс Наблюдателя
interface Observer {
    void update(String stockSymbol, double stockPrice);
}

// Конкретный Субъект (Биржевой тикер)
class StockTicker {
    private String symbol;
    private double price;
    private List<Observer> investors = new ArrayList<>();

    public void setPrice(double price) {
        this.price = price;
        notifyObservers(); // Критический шаг: уведомляем всех при изменении
    }

    public void attach(Observer o) { investors.add(o); }
    public void detach(Observer o) { investors.remove(o); }

    private void notifyObservers() {
        for (Observer investor : investors) {
            investor.update(symbol, price);
        }
    }
}

// Конкретный Наблюдатель
class Investor implements Observer {
    private String name;
    public Investor(String name) { this.name = name; }

    @Override
    public void update(String symbol, double price) {
        System.out.printf("Инвестор %s: Акция %s теперь стоит $%.2f%n", name, symbol, price);
    }
}

// Использование
StockTicker appleStock = new StockTicker("AAPL", 150.0);
Investor alice = new Investor("Alice");
Investor bob = new Investor("Bob");

appleStock.attach(alice);
appleStock.attach(bob);

appleStock.setPrice(155.5);
// Вывод:
// Инвестор Alice: Акция AAPL теперь стоит $155.50
// Инвестор Bob: Акция AAPL теперь стоит $155.50

Применение: Системы событий в GUI, реактивное программирование (RxJava), модель MVC, уведомления в микросервисах.