Skip to content
This repository was archived by the owner on Jun 23, 2023. It is now read-only.

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

Observer

To implement a publish/subscribe behaviour to an object, whenever a "Subject" object changes its state, the attached "Observers" will be notified. It is used to shorten the amount of coupled objects and uses loose coupling instead.

UML

Observer

Code

User.php

<?php

namespace Kuriv\PHPDesignPatterns\Behavioral\Observer;

use SplSubject;
use SplObjectStorage;
use SplObserver;

class User implements SplSubject
{
    /**
     * Store the email.
     *
     * @var string
     */
    private string $email;

    /**
     * Store the object storage instance.
     *
     * @var SplObjectStorage
     */
    private SplObjectStorage $observers;

    /**
     * Store the object storage instance to the current instance.
     *
     * @param  void
     * @return void
     */
    public function __construct()
    {
        $this->observers = new SplObjectStorage;
    }

    /**
     * Attach an observer instance.
     *
     * @param  SplObserver $observer
     * @return void
     */
    public function attach(SplObserver $observer)
    {
        $this->observers->attach($observer);
    }

    /**
     * Detach an observer instance.
     *
     * @param  SplObserver $observer
     * @return void
     */
    public function detach(SplObserver $observer)
    {
        $this->observers->detach($observer);
    }

    /**
     * Change the email and notify.
     *
     * @param  string $email
     * @return void
     */
    public function changeEmail(string $email)
    {
        $this->email = $email;
        $this->notify();
    }

    /**
     * Perform notify action.
     *
     * @param  void
     * @return void
     */
    public function notify()
    {
        foreach ($this->observers as $observer) {
            $observer->update($this);
        }
    }
}

UserObserver.php

<?php

namespace Kuriv\PHPDesignPatterns\Behavioral\Observer;

use SplObserver;
use SplSubject;

class UserObserver implements SplObserver
{
    /**
     * Store the changed users.
     *
     * @var array
     */
    private array $changedUsers = [];

    /**
     * Update the property.
     *
     * @param  SplSubject $subject
     * @return void
     */
    public function update(SplSubject $subject)
    {
        $this->changedUsers[] = clone $subject;
    }

    /**
     * Get all changed users.
     *
     * @param  void
     * @return array
     */
    public function getChangedUsers(): array
    {
        return $this->changedUsers;
    }
}

Test

ObserverTest.php

<?php

namespace Kuriv\PHPDesignPatterns\Behavioral\Observer;

use PHPUnit\Framework\TestCase;

class ObserverTest extends TestCase
{
    public function testChangeInUserLeadsToUserObserverBeingNotified()
    {
        $user = new User();
        $observer = new UserObserver();
        $user->attach($observer);
        $user->changeEmail('foo@foo.com');
        $this->assertCount(1, $observer->getChangedUsers());
    }
}