Заметки WEB-разработчика

Полезные материалы для web-разработки

Шаблон проектирования Observer или Listener (наблюдатель, слушатель)

В этой статье речь пойдет о шаблоне проектирования Observer или Listener (наблюдатель, слушатель) и как этот паттерн применяется в php.

Аналогия

Очень распространенный паттерн в реальной жизни. Например если вы подписались на какую-либо email (или смс) рассылку, то ваш email (или номер сотового телефона) начинает реализовывать паттерн «наблюдатель». Как только вы подписываетесь на событие (например новая статья или сообщение), всем кто подписан на это событие (наблюдателям) будет выслано уведомление, а они уже в свою очередь могут выбрать как на это сообщение реагировать.

Подходящий видос для объяснения:

 

Схема

Элементарный пример

interface Observable
{
    /**
     * Добавление новго наблюдателя
     *
     * @param Observer $instance
     * @return bool
     */
    public function attach(Observer $instance);

    /**
     * Оповещение всех наблюдателей, через вызов у него метода update
     *
     */
    public function notify();
}

interface Observer
{
    /**
     * Будет вызван у каждого наблюдателя в notify()
     *
     * @param Observable $instance
     * @return mixed
     */
    public function update(Observable $instance);
}

Class Journal implements Observable
{

    /**
     * Массив наблюдателей
     *
     * @var Observer[]
     */
    private $observers = array();


    public function attach(Observer $instance) {
        foreach ($this->observers as $observer) {
            if ($instance === $observer) {
                return false;
            }
        }

        $this->observers[] = $instance;
        return true;
    }


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

    /**
     * Когда журнал публикуется, он вызывает оповещение всех наблюдателей
     *
     */
    public function published(){
        $this->notify();
    }
}

Class User1 implements Observer
{
    private $_email = 'user1@tut.by';
    private $_subject = 'New mail to user1';
    private $_body = 'Hi, User1, I`m a new Journal';

    public function userMail()
    {
        mail($this->_email, $this->_subject, $this->_body);
        echo 'new notification sent to user 1';
    }
    public function update(Observable $instance)
    {
        $this->userMail();
    }
}

Class User2 implements Observer
{
    private $_email = 'user2@tut.by';
    private $_subject = 'New mail to user2';
    private $_body = 'Hi, User2, I`m a new Journal';

    public function userMail()
    {
        mail($this->_email, $this->_subject, $this->_body);
        echo 'new notification sent to user2';
    }

    public function update(Observable $instance)
    {
        $this->userMail();
    }
}

$comment = new Journal();
$comment->attach(new User2);
$comment->attach(new User1);
$comment->published();

Комментарии

Комментарии через Вконтакте