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

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

Ответ

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

Зачем он нужен? Чтобы обеспечить слабую связанность: субъекту не нужно знать конкретные классы наблюдателей, а только общий интерфейс. Это упрощает добавление новых наблюдателей и переиспользование кода.

Пример реализации на PHP:

// Интерфейс Наблюдателя
interface ObserverInterface {
    public function update(SubjectInterface $subject): void;
}

// Интерфейс Субъекта
interface SubjectInterface {
    public function attach(ObserverInterface $observer): void;
    public function detach(ObserverInterface $observer): void;
    public function notify(): void;
}

// Конкретный Субъект (например, система заказов)
class OrderService implements SubjectInterface {
    private $observers = [];
    private $orderStatus;

    public function attach(ObserverInterface $observer): void {
        $this->observers[] = $observer;
    }

    public function notify(): void {
        foreach ($this->observers as $observer) {
            $observer->update($this);
        }
    }

    public function setStatus(string $status): void {
        $this->orderStatus = $status;
        $this->notify(); // Уведомляем всех подписчиков об изменении
    }

    public function getStatus(): string {
        return $this->orderStatus;
    }
}

// Конкретный Наблюдатель (например, сервис нотификаций)
class EmailNotifier implements ObserverInterface {
    public function update(SubjectInterface $subject): void {
        if ($subject instanceof OrderService && $subject->getStatus() === 'shipped') {
            echo "Отправляем email клиенту: ваш заказ отправлен.n";
        }
    }
}

// Использование
$order = new OrderService();
$order->attach(new EmailNotifier());
$order->setStatus('shipped'); // Автоматически вызовет отправку email

Где я применял: В одном из проектов на Laravel мы использовали этот паттерн через встроенную систему событий (Event / Listener), которая является его реализацией, для отправки уведомлений, логирования и обновления кэша при изменении данных.