Шаблон Observer (Наблюдатель)
02-11-2019Время чтения ~ 2 мин.PHP/ООП 6569
Поведенческий шаблон Наблюдатель реализует механизм, с момощью которого один класс может уведомлять другие о своём изменении. Практическая реализация кода может быть разной, но в PHP уже существуют готовые стандартные интерфейсы SplSubject, SplObjectStorage и SplObserver, на которых и принято реализовывать паттерн Observer.
Стоит отметить, что сам по себе этот шаблон родом из «больших» языков. Я уже рассказывал о его реализации для Java, где класс Модели отправляет уведомления о своём изменении всем своим «слушателям».
Исходный код вы найдёте на гитхабе. Рассмотрим его подробней.
Класс Наблюдатель (Observable) реализует интерфейс SplSubject. В этом классе хранятся «слушатели» — объекты стандартного класса SplObjectStorage. С помощью метода attach()
добавляется новый «слушатель». Удалить его можно с помощью detach()
.
Также есть метод notify()
которые «отправляет» уведомление об изменениях в классе «наблюдателя» всем своим «слушателям».
Каждый слушатель реализует стандартный интерфейс SplObserver и должен содержать метод update()
. Собственно этот метод и используется в качестве «события».
Использование паттерна происходит по такой схеме. Вначале инстанцируется основной класс (Наблюдатель), после классы «слушателей», которые нужно зарегистрировать у Наблюдателя. Дальше, как только Наблюдателю нужно отправить уведомление вызывается метод notify()
, который в свою очередь выполнит методы update()
подчинённых классов.
В «больших» языках шаблон Observer имеет практический смысл, поскольку программы работают в событийной среде ОС. Например когда нажимается кнопка мыши, то Windows генерирует событие WM_LBUTTONDOWN, которое может перехватить программа. После этого программа всё также работает и функция для обработки нажатия кнопки просто ждёт когда придёт новое событие от операционной системы.
PHP — функциональный язык, где нет места событийности, поэтому шаблон Observer нужно рассматривать в более примитивной форме: по сути это просто вызов методов из «родительского» класса, где задача сводится только к тому, указать классы слушателей и вызвать какой-то предопределённый метод.