Шаблон проектирования Observer
Шаблон проектирования Observer относится к поведенческим паттернам и предназначен для реализации механизма подписки объектов друг на друга. Основная идея заключается в том, что один объект («наблюдатель») подписывается на изменения состояния другого объекта («субъекта»), чтобы получать уведомления о произошедших изменениях и реагировать соответствующим образом.
Основные элементы шаблона Observer
Субъект (Subject
)
Объект, состояние которого отслеживается наблюдателями. Его основные обязанности:
- Регистрация новых подписчиков (наблюдателей).
- Удаление подписчиков.
- Уведомление всех зарегистрированных наблюдателей о наступлении события или изменении своего состояния.
Наблюдатели (Observers
)
Наблюдатели — объекты, интересующиеся изменениями состояния субъекта. Их задача — обрабатывать уведомление, отправленное субъектом, и предпринимать необходимые действия.
Пример реализации на PHP
Представим ситуацию, когда нам нужно создать простую систему уведомлений пользователей сайта о поступивших комментариях на посты.
<?php
// Интерфейс Subject
interface Subject {
public function attach($observer);
public function detach($observer);
public function notify();
}
// Реализация Subject
class Post implements Subject {
private array $observers = [];
private string $title;
private int $commentsCount = 0;
// Конструктор поста
public function __construct(string $title)
{
$this->title = $title;
}
// Добавляем нового наблюдателя
public function attach($observer): void
{
if (!in_array($observer, $this->observers)) {
$this->observers[] = $observer;
}
}
// Отписываем наблюдателя
public function detach($observer): void
{
foreach ($this->observers as $key => $value) {
if ($value === $observer) {
unset($this->observers[$key]);
}
}
}
// Оповещаем всех наблюдателей
public function notify(): void
{
foreach ($this->observers as $observer) {
$observer->update($this); // Передаем ссылку на себя
}
}
// Метод обновления комментариев
public function addComment()
{
$this->commentsCount++;
echo 'Новый комментарий! Общее количество: ' . $this->commentsCount . "\n";
$this->notify(); // После добавления комментария оповещаем всех наблюдателей
}
// Получаем название поста
public function getTitle(): string
{
return $this->title;
}
// Получаем количество комментариев
public function getCommentsCount(): int
{
return $this->commentsCount;
}
}
// Интерфейс Observer
interface Observer {
public function update(Subject $subject);
}
// Реализация конкретного наблюдателя (например, Email-подписчик)
class UserEmail implements Observer {
private string $email;
public function __construct(string $email)
{
$this->email = $email;
}
// Метод обработки изменений
public function update(Subject $subject): void
{
echo 'Отправлено письмо на адрес ' . $this->email .
': Пост "' . $subject->getTitle() . '" получил новый комментарий!' . "\n";
}
}
// Создаем пост
$post = new Post('Обзор iPhone 15');
// Подписчики
$user1 = new UserEmail('ivan@example.com');
$user2 = new UserEmail('mariia@example.com');
// Регистрируем наблюдателей
$post->attach($user1);
$post->attach($user2);
// Моделируем действие комментирования
for ($i = 0; $i < 3; $i++) {
$post->addComment();
}
Как работает этот пример?
- Мы создаем класс
Post
, который реализует интерфейсSubject
. Этот класс управляет списком подписчиков и вызывает методnotify()
всякий раз, когда добавляется новый комментарий. - Затем мы определяем наблюдателей, реализуя интерфейс
Observer
в классеUserEmail
. Каждый экземпляр класса представляет собой одного подписчика, ожидающего уведомлений о появлении новых комментариев. - Когда происходит событие (добавляется комментарий), каждый зарегистрированный наблюдатель получает уведомление и выполняет своё действие (отправляет email-сообщение).
Преимущества шаблона Observer:
- Позволяет реализовать гибкую связь между объектами, не связывая их жестко друг с другом.
- Удобство масштабируемости системы благодаря возможности легко добавлять/удалять новые типы наблюдателей.
- Улучшение производительности путем ограничения операций обновлений лишь теми объектами, которым действительно нужны уведомления.
Таким образом, шаблон Observer является полезным инструментом для разработки веб-приложений на PHP, особенно там, где необходима динамическая реакция компонентов на изменение состояния других элементов приложения.