Паттерн Спостерігач (Observer) в PHP
Мітки: patterns, php, observer
Паттерн Наблюдатель (Observer) в PHP
Observer pattern in PHP
| ← Робота з форматами стиснення RAR, LZF і Bz2 в PHP | Визначення і використання власних подій в Javascript → |
Зовсім недавно я просто закохався в шаблон проектування observer. Ви можете з легкістю побудувати повний додаток, використовуючи неймовірну міць програмування управлінь подіями. Що саме представляє з себе паттерн спостерігач? Вся теорія доступна на Вікіпедії. Говорячи простою мовою, у нас є об'єкт, за яким ми хочемо моніторити (спостерігати) на предмет якихось змін. Більшість часу цей об'єкт просто звільняє події і ми хочемо прослуховувати їх. Ми можемо мати багато об'єктів прослуховуючих один або багато інших об'єктів, простіше кажучи, це може бути відносини багато до багатьох. Класичний приклад у світі баз даних це тригери. Наприклад, коли таблиця була оновлена, тригер, що прослуховує, звільняється. У віконних додатках, коли користувач натискає на кнопку, події звільняються і ті що прослуховують повідомляються для керування подією. У наступному прикладі ми маємо об'єкт валідатору, який перевіряє валідність e-mail адреси, звільняються два типи подій, які б ми хотіли прослуховувати. Ці типи, ясна річ, дійсний / не дійсний e-mail адресу. Ми також оголосимо двох слухачів, по одному на кожний з типів подій, слухаючих валідатор. Перший буде просто деяким логгером помилок, записувати невірні спроби введення, і другий буде записувати коректний e-mail адрес в базу даних або інше місце. Ми почнемо з опису нашого інтерфейсу для об’єкту спостереження. Ми просто хочемо додати спостерігачів та звільнити події. Також ми хочемо мати можливість прослуховувати тільки певні типи подій, значить, у нас немає необхідності сповіщати спостерігачів не слухати подію, яка тільки що звільнилася.
Прибрати підсвітку коду
Отже, будь-який об'єкт, який ми хочемо спостерігати, повинен описувати інтерфейс IObservable. Давайте опишемо, як має виглядати спостерігач. По простому, спостерігачеві необхідно лише знати, що об'єкт звільнив подію і тип цієї події, значить, вона може бути оброблена.
Прибрати підсвітку коду
Зараз ми зробимо наш e-mail валідатора, який описує інтерфейс IObservable і визначає два типи подій.
Прибрати підсвітку коду
Метод, який виконує всю роботу - це validate(). Він просто перевіряє отриманий e-mail та звільняє валідну або невалідну подію.
Це все, про решту піклуються спостерігачі. Давайте зробимо двох спостерігачів, кожен з яких буде слухати різні типи подій. Це спостерігач ErrorLogger, який буде сповіщені кожен раз, коли e-mail, що перевіряється, не дійсний. Він може писати щось в лог або просто попереджувати користувача.
Прибрати підсвітку коду
Просто, чи не так. ErrorLogger тільки описує метод notify () і перевіряє чи подія являється EmailValidator і тип цієї події EVENT_EMAIL_INVALID, а потім пише повідомлення про помилку. Спостерігач для EVENT_EMAIL_VALID виглядає дуже схоже.
Прибрати підсвітку коду
Це воно. Тепер нам всього лише необхідно створити наш об'єкт EmailValidator, додати деяких спостерігачів і дати їм кілька e-mail адрес на перевірку.
Прибрати підсвітку коду
Виконавши ці приклади, повинен вийти приблизно такий результат:
Прибрати підсвітку коду
Це був лише простий приклад, що демонструє міць паттерну спостерігач. Я впевнений, що ви знайдете багато застосувань для нього.
Оригінал: Observer pattern in PHP
Прибрати підсвітку коду
1 2 3 4 5 6 | interface IObservable { public function addObserver( IObserver $objObserver, $strEventType ); public function fireEvent( $strEventType ); } |
Отже, будь-який об'єкт, який ми хочемо спостерігати, повинен описувати інтерфейс IObservable. Давайте опишемо, як має виглядати спостерігач. По простому, спостерігачеві необхідно лише знати, що об'єкт звільнив подію і тип цієї події, значить, вона може бути оброблена.
Прибрати підсвітку коду
1 2 3 4 5 | interface IObserver { public function notify( IObservable $objSource, $objArguments ); } |
Зараз ми зробимо наш e-mail валідатора, який описує інтерфейс IObservable і визначає два типи подій.
Прибрати підсвітку коду
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | class EmailValidator implements IObservable { const EVENT_EMAIL_VALID = 1; const EVENT_EMAIL_INVALID = 2; protected $strEmailAddress; protected $aryObserversArray; public function __construct( $strEmailAddress ) { $this->strEmailAddress = $strEmailAddress; $this->aryObserversArray = array( array() ); } public function setEmailAddress( $strEmailAddress ) { $this->strEmailAddress = $strEmailAddress; } public function getEmailAddress() { return $this->strEmailAddress; } public function validate() { if( preg_match( '/^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@'. '[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$/', $this->strEmailAddress ) ) { $this->fireEvent( EmailValidator::EVENT_EMAIL_VALID ); } else { $this->fireEvent( EmailValidator::EVENT_EMAIL_INVALID ); } } public function addObserver( IObserver $objObserver, $strEventType ) { $this->aryObserversArray[$strEventType][] = $objObserver; } public function fireEvent( $strEventType ) { if( is_array( $this->aryObserversArray[$strEventType] ) ) { foreach ( $this->aryObserversArray[$strEventType] as $objObserver ) { $objObserver->notify( $this, $strEventType ); } } } } |
Метод, який виконує всю роботу - це validate(). Він просто перевіряє отриманий e-mail та звільняє валідну або невалідну подію.
Це все, про решту піклуються спостерігачі. Давайте зробимо двох спостерігачів, кожен з яких буде слухати різні типи подій. Це спостерігач ErrorLogger, який буде сповіщені кожен раз, коли e-mail, що перевіряється, не дійсний. Він може писати щось в лог або просто попереджувати користувача.
Прибрати підсвітку коду
1 2 3 4 5 6 7 8 9 10 11 12 | class ErrorLogger implements IObserver { public function notify( IObservable $objSource, $strEventType ) { if( $strEventType == EmailValidator::EVENT_EMAIL_INVALID && $objSource instanceof EmailValidator ) { printf( 'Помилка:% s невалідний email', $objSource->getEmailAddress() ); } } } |
Просто, чи не так. ErrorLogger тільки описує метод notify () і перевіряє чи подія являється EmailValidator і тип цієї події EVENT_EMAIL_INVALID, а потім пише повідомлення про помилку. Спостерігач для EVENT_EMAIL_VALID виглядає дуже схоже.
Прибрати підсвітку коду
1 2 3 4 5 6 7 8 9 10 11 12 | class DatabaseWriter implements IObserver { public function notify( IObservable $objSource, $strEventType ) { if( $strEventType == EmailValidator::EVENT_EMAIL_VALID && $objSource instanceof EmailValidator ) { printf('Email адреса %s дійсна і була записана до бази даних', $objSource->getEmailAddress() ); } } } |
Це воно. Тепер нам всього лише необхідно створити наш об'єкт EmailValidator, додати деяких спостерігачів і дати їм кілька e-mail адрес на перевірку.
Прибрати підсвітку коду
1 2 3 4 5 6 7 8 | $objValidator = new EmailValidator( 'valid@email.com' ); $objValidator->addObserver( new ErrorLogger(), EmailValidator::EVENT_EMAIL_INVALID ); $objValidator->addObserver( new DatabaseWriter(), EmailValidator::EVENT_EMAIL_VALID ); $objValidator->validate(); $objValidator->setEmailAddress( 'not_a_valid_address' ); $objValidator->validate(); |
Виконавши ці приклади, повинен вийти приблизно такий результат:
Прибрати підсвітку коду
1 2 | Помилка: not_a_valid_address невалідний email.
Email адреса valid@email.com Дійсний і було записано в базу даних |
Це був лише простий приклад, що демонструє міць паттерну спостерігач. Я впевнений, що ви знайдете багато застосувань для нього.
Оригінал: Observer pattern in PHP
Рейтинг:




<< Ви можете поставити оцінку цій статтіПодібні статті:
Паттерн кешування для моделей
Робота з форматами стиснення RAR, LZF і Bz2 в PHP
MVC в невеликих web-додатках
Обговорення статті:
GrAndSE [2009-08-26]
Чудова стаття. Нажаль, дуже мало php-програмістів користуються патернами проектування :(