Статья
Шаблон проектирования "Наблюдатель"

Шаблон проектирования "Наблюдатель"

29 мая 2020

Относится к поведенческим шаблонам.

Имеется объект, ведущий список своих "подчиненных" и автоматически уведомляющий их об изменении своего состояния.


Пример на PHP

В PHP (начиная с 5.1) имеются интерфейсы SplObserver и SplSubject, позволяющие реализовать шаблон "Наблюдатель".

Класс, получающий уведомления:

class UserObserver implements \SplObserver
{
    public function update(\SplSubject $subject)
    {
    }
}

Класс, отправляющий уведомления:

class User implements \SplSubject
{
    private string $email;

    private array $observers = [];

    public function __construct()
    {
        $this->observers = new \SplObjectStorage();
    }

    public function attach(\SplObserver $observer)
    {
        $this->observers->attach($observer);
    }

    public function detach(\SplObserver $observer)
    {
        $this->observers->detach($observer);
    }

    public function changeEmail(string $email)
    {
        $this->email = $email;
        $this->notify();
    }

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

Использование:

$observer = new UserObserver();

$user = new User();
$user->attach($observer);
$user->changeEmail('test@test.com');


Пример на Go

package main

type IUser interface {
   Attach(observer IUserObserver)
   ChangeEmail(email string)
}

type IUserObserver interface {
   Update(user IUser)
}

type User struct {
   email string
   observers []IUserObserver
}

func (u *User) Attach(observer IUserObserver) {
   u.observers = append(u.observers, observer)
}

func (u *User) ChangeEmail(email string) {
   u.email = email
   u.notify()
}

func (u *User) notify() {
   for _, v := range u.observers {
      v.Update(u)
   }
}

type UserObserver struct {
}

func (o *UserObserver) Update(user IUser) {
   // требуемые действия
}

func main() {
   observer := UserObserver{}
   
   user := User{}
   user.Attach(&observer)
   user.ChangeEmail("test@test.com")
}



Источники:
http://designpatternsphp.readthedocs.io/ru/latest/Behavioral/Observer/README.html
https://habrahabr.ru/company/mailru/blog/325492/