3.8. Observador (Observer)¶
3.8.1. Objetivo¶
Implementar um comportamento de publicação/subscrição para um objeto, sempre que um objeto “Sujeito” altera o seu estado, o “Observador” anexo será notificado. Ele é usado para ordenar a massa de objetos combinados e usa baixo acoplamento em seu lugar.
3.8.2. Exemplos¶
- um sistema de fila de mensagem é observado para apresentar o progresso de um trabalho na interface gráfica do usuário (GUI)
3.8.3. Nota¶
O PHP já define duas interfaces que podem ajudar a implementar este padrão: SplObserver e SplSubject.
3.8.4. Diagrama UML¶

3.8.5. Código¶
Você também pode encontrar este código no GitHub
User.php
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 | <?php
declare(strict_types=1);
namespace DesignPatterns\Behavioral\Observer;
use SplSubject;
use SplObjectStorage;
use SplObserver;
/**
* User implements the observed object (called Subject), it maintains a list of observers and sends notifications to
* them in case changes are made on the User object
*/
class User implements SplSubject
{
private SplObjectStorage $observers;
private $email;
public function __construct()
{
$this->observers = new SplObjectStorage();
}
public function attach(SplObserver $observer): void
{
$this->observers->attach($observer);
}
public function detach(SplObserver $observer): void
{
$this->observers->detach($observer);
}
public function changeEmail(string $email): void
{
$this->email = $email;
$this->notify();
}
public function notify(): void
{
/** @var SplObserver $observer */
foreach ($this->observers as $observer) {
$observer->update($this);
}
}
}
|
UserObserver.php
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 | <?php
declare(strict_types=1);
namespace DesignPatterns\Behavioral\Observer;
use SplObserver;
use SplSubject;
class UserObserver implements SplObserver
{
/**
* @var SplSubject[]
*/
private array $changedUsers = [];
/**
* It is called by the Subject, usually by SplSubject::notify()
*/
public function update(SplSubject $subject): void
{
$this->changedUsers[] = clone $subject;
}
/**
* @return SplSubject[]
*/
public function getChangedUsers(): array
{
return $this->changedUsers;
}
}
|
3.8.6. Teste¶
Tests/ObserverTest.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <?php
declare(strict_types=1);
namespace DesignPatterns\Behavioral\Observer\Tests;
use DesignPatterns\Behavioral\Observer\User;
use DesignPatterns\Behavioral\Observer\UserObserver;
use PHPUnit\Framework\TestCase;
class ObserverTest extends TestCase
{
public function testChangeInUserLeadsToUserObserverBeingNotified()
{
$observer = new UserObserver();
$user = new User();
$user->attach($observer);
$user->changeEmail('foo@bar.com');
$this->assertCount(1, $observer->getChangedUsers());
}
}
|