Observer Pattern – PHP

Olá pessoas!

Este é primeira postagem do meu blog e irei falar um pouco sobre o pattern Observer.

Este padrão vai definir uma dependência de um objeto para muitos. “Oh, mas como assim? Exemplifique!”. Ok:

Vamos imaginar uma revista. O que uma revista precisa? De assinaturas! E vocês não concordam que quando essa revista lançar uma nova edição, essa edição será entregue na mesma hora para todos os assinantes (não na mesma hora, mas vai ser enviada na mesma hora)? E que qualquer destes assinantes tem o direito de cancelar essa assinatura a qualquer momento? Então, o pattern Observer é exatamente isso!

Para esse pattern, são necessárias dois participantes: Subject (revista) e Observer (assinante).

interface Subject{
    public function attach( Observer $observer );
    public function dettach( Observer $observer );
    public function notify();
}

attach: Adiciona um observador
remove: Remove um observador
notify: Notifica os observadores

interface Observer{
    public function update( Subject $subject );
}

update: Recebe as atualizações do sujeito

Definidas as interfaces dos nossos participantes, vamos ao código da revista:

class Magazine implements Subject{
    private $subscribers = array();
    private $edition;

    public function __construct( $name ){
        $this->name = $name;
    }

    public function attach( Observer $observer ){
        if( $this->isSubscriber( $observer ) ){
            throw new InvalidArgumentException( 'Subscriber has already added' );
        }

        $this->subscribers[] = $observer;
    }

    public function dettach( Observer $observer ){
        $key = array_search( $observer, $this->subscribers );

        if( $key !== false ){
            unset( $this->subscribers[ $key ] );
        }
    }

    public function notify(){
        foreach( $this->subscribers as $subscriber ){
            $subscriber->update( $this );
        }
    }

    public function newEdition( $edition ){
        $this->edition = $edition;
        $this->notify();
    }

    public function getEdition(){
        return $this->edition;
    }

    public function getName(){
        return $this->name;
    }

    private function isSubscriber( Observer $observer ){
        return in_array( $observer, $this->subscribers );
    }
}

E o código do assinante:

class Subscriber implements Observer{
    private $name;

    public function __construct( $name ){
        $this->name = $name;
    }

    public function update( Subject $subject ){
        $magazine = $subject->getName();
        $edition = $subject->getEdition();

        echo $this->name . ' is reading edition number ' . $edition . ' of the ' . $magazine;
    }
}

Agora vamos simular:

$subscriber1 = new Subscriber( 'Gabriel' );
$subscriber2 = new Subscriber( 'João' );

$magazine = new Magazine( 'Olhe' );
$magazine->attach( $subscriber1 );
$magazine->attach( $subscriber2 );
$magazine->newEdition( '12' );
$magazine->dettach( $subscriber2 );
$magazine->newEdition( '13' );

//12:
//Gabriel is reading edition number 12 of the Olhe
//João is reading edition number 12 of the Olhe
//13:
//Gabriel is reading edition number 13 of the Olhe

Conclusão: com esse padrão, como vimos, é possível compartilhar um determinado recurso com vários participantes de uma vez só, sem se preocupar se vai faltar algum.
Bom, então é isso, nos vemos por ai com mais algum artigo 🙂

Comente