Utilzando o Design Pattern OBSERVER utilizando as interfaces SPL (STANDARD PHP LIBRARY)
Definição:
A utilização é um objeto que será observado por um ou mais objetos , que são os observadores, que obviamente são associados como observadores deste objeto, e quando o observador disparar um método de notificação, todos os objetos associados (os observadores) executarão cada um sua rotina específica, assim fazendo com que o processo seja organizado e evitando colocar instancias de objetos dentro de outros objetos ou até mesmo um aninhado de instancias para cada objeto que irá executar algo.
Utilização:
Utilizarem duas interfaces já disponíveis no PHP chamadas de SplObserver e SplSubject, disponíveis dês do começo do PHP 5.1.xxxx
- Interface SplSubject: é a interface que será implementada no Observado. contém os metodos attach e detach e notify
-- attach: Adiciona observadores ao objeto.
-- detach: Remove observadores.
-- notify: Envia a notificação para todos os observadores do objeto.
- Interface SplObject: é a interface do observador. contém somente o método update.
NOTA: Todos os métodos dessas interfaces, são explícitos em relação aos métodos, chamados de type-hint, ou seja , para o método attach só deve ser enviado como parâmetro um objeto do tipo SplObserver, o mesmo para o detach, tudo isso existe uma documentação, e vou colocar um código de exemplo.
Desenvolvendo:
Vamos primeiro criar a classe que será observada pelos demais objetos, chamaremos ela de Materia
Feito isso, criaremos uma classe de Professor.
Criaremos agora uma classe de Aluno.
Com as classes criadas, iremos associar os observadores na classe observada e depois notificaremos.
O output esperado é esse:
Esse é um exemplo simples de como utilizar um observer sem precisar colocar uma instância do professor e aluno dentro da matéria. Pode ser feito muito mais com isso, como por exemplo um observer que ao cadastrar uma pessoa, envia um email para o admin. Use a imaginação e espero que gostem
Qualquer dúvida, crítica, sugestão ou incentivo para escrever mais artigos, por favor envie um comentário abaixo.
Abraços!
A utilização é um objeto que será observado por um ou mais objetos , que são os observadores, que obviamente são associados como observadores deste objeto, e quando o observador disparar um método de notificação, todos os objetos associados (os observadores) executarão cada um sua rotina específica, assim fazendo com que o processo seja organizado e evitando colocar instancias de objetos dentro de outros objetos ou até mesmo um aninhado de instancias para cada objeto que irá executar algo.
Utilização:
Utilizarem duas interfaces já disponíveis no PHP chamadas de SplObserver e SplSubject, disponíveis dês do começo do PHP 5.1.xxxx
- Interface SplSubject: é a interface que será implementada no Observado. contém os metodos attach e detach e notify
-- attach: Adiciona observadores ao objeto.
-- detach: Remove observadores.
-- notify: Envia a notificação para todos os observadores do objeto.
- Interface SplObject: é a interface do observador. contém somente o método update.
NOTA: Todos os métodos dessas interfaces, são explícitos em relação aos métodos, chamados de type-hint, ou seja , para o método attach só deve ser enviado como parâmetro um objeto do tipo SplObserver, o mesmo para o detach, tudo isso existe uma documentação, e vou colocar um código de exemplo.
Desenvolvendo:
Vamos primeiro criar a classe que será observada pelos demais objetos, chamaremos ela de Materia
<?php class Materia implements SplSubject { private $nome_materia; // Os observadores é um array onde ele guardará todas as instâncias dos objetos que forem adicionados private $_observadores = array(); // Coloquei um array de log só para mostrar o funcionamento do Observer private $_log = array(); // Encapsuladores public function GET_materia() { return $this->nome_materia; } function SET_log($valor) { $this->_log[] = $valor ; } function GET_log() { return $this->_log; } // Função construtora que irá somente associar um nome ao professor function __construct($nome) { $this->nome_materia = $nome; $this->_log[] = " Materia $nome foi incluida com sucesso"; } // Implementa o método attach do SplSubject, enviando como parâmetro um observador e associando ao array de objetos public function attach(SplObserver $classes) { $this->_classes[] = $classes; $this->_log[] = " O ".$classes->GET_tipo()." ".$classes->GET_nome()." foi adicionado"; } // Implementa o método detach do SplSubject, que somente remove a instância do objeto public function detach(SplObserver $classes) { foreach ($this->_classes as $key => $obj){ if ($obj == $classes){ unset($this->_classes[$key]); $this->_log[] = " O ".$classes->GET_tipo()." ".$classes->GET_nome()." foi removido"; } } } // Implementa o método notify do SplSubject, que percorre todo o array de observadores e chama o método update de do observador, que esta implementado dentro da sua classe public function notify() { foreach ($this->_classes as $classes){ $classes->update($this); } } } ?>
Feito isso, criaremos uma classe de Professor.
<?php class Professor implements SplObserver { protected $tipo = "Professor"; private $nome; private $endereco; private $telefone; private $email; // Encapsulador public function GET_tipo() { return $this->tipo; } public function GET_nome() { return $this->nome; } public function GET_email() { return $this->email; } public function GET_telefone() { return $this->nome; } // Construtor que somente associa o nome do professor function __construct($nome) { $this->nome = $nome; } // Implementa o método update do SplObserver, que executa o método de acordo com a necessidade do objeto Professor public function update(SplSubject $object) { $object->SET_log("Vindo de ".$this->nome.": Dou aula de ".$object->GET_materia()); } } ?>
Criaremos agora uma classe de Aluno.
<?php class Aluno implements SplObserver { protected $tipo = "Aluno"; private $nome; private $endereco; private $telefone; private $email; // Encapsulador public function GET_tipo(){ return $this->tipo; } public function GET_nome() { return $this->nome; } public function GET_email() { return $this->email; } public function GET_telefone() { return $this->nome; } // Construtor que somente associa o nome do aluno function __construct($nome) { $this->nome = $nome; } // Implementa o método update do SplObserver, que executa o método de acordo com a necessidade do objeto Aluno public function update(SplSubject $object) { $object->SET_log("Vindo de ".$this->nome.": Sou aluno de ".$object->GET_materia()); } } ?>
Com as classes criadas, iremos associar os observadores na classe observada e depois notificaremos.
<?php require_once("professor.class.php"); require_once("aluno.class.php"); require_once("materia.class.php"); $materia = new Materia("Matematica"); $marcus = new Professor("Marcus"); $rafael = new Aluno("Rafael"); $vinicius = new Aluno("Vinicius"); // Associando os observadores no objeto Materia Matemática $materia->attach($rafael); $materia->attach($vinicius); $materia->attach($marcus); $materia2 = new Materia("Portugues"); $renato = new Professor("Renato"); $fabio = new Aluno("Fabio"); $tiago = new Aluno("tiago"); // Associando os observadores no objeto Materia Portugues $materia2->attach($renato); $materia2->attach($vinicius); $materia2->attach($fabio); $materia2->attach($tiago); // Removendo Alunos da Materia 1 $materia->detach($rafael); // Notificando as 2 Matérias $materia->notify(); $materia2->notify(); echo "Materia 1 <br>"; echo "<pre>"; print_r($materia->GET_log()); echo "</pre>"; echo "<hr>"; echo "Materia 2 <br>"; echo "<pre>"; print_r($materia2->GET_log()); echo "</pre>"; ?>
O output esperado é esse:
Materia 1 Array ( [0] => Materia Matematica foi incluida com sucesso [1] => O Aluno Rafael foi adicionado [2] => O Aluno Vinicius foi adicionado [3] => O Professor Marcus foi adicionado [4] => O Aluno Rafael foi removido [5] => Vindo de Vinicius: Sou aluno de Matematica [6] => Vindo de Marcus: Dou aula de Matematica ) -------------------------------------------------------------------------------- Materia 2 Array ( [0] => Materia Portugues foi incluida com sucesso [1] => O Professor Renato foi adicionado [2] => O Aluno Vinicius foi adicionado [3] => O Aluno Fabio foi adicionado [4] => O Aluno tiago foi adicionado [5] => Vindo de Renato: Dou aula de Portugues [6] => Vindo de Vinicius: Sou aluno de Portugues [7] => Vindo de Fabio: Sou aluno de Portugues [8] => Vindo de tiago: Sou aluno de Portugues )
Esse é um exemplo simples de como utilizar um observer sem precisar colocar uma instância do professor e aluno dentro da matéria. Pode ser feito muito mais com isso, como por exemplo um observer que ao cadastrar uma pessoa, envia um email para o admin. Use a imaginação e espero que gostem
Qualquer dúvida, crítica, sugestão ou incentivo para escrever mais artigos, por favor envie um comentário abaixo.
Abraços!
Ótimo artigo!
Não sabia que o SPL possui interfaces para o Observer, bom saber!!
Abs,
Alex
Não sabia que o SPL possui interfaces para o Observer, bom saber!!
Abs,
Alex
25/05/2009 5:18pm
(~15 anos atrás)
<?php
class Observer {
}
classe Subject {
}
?>
Que vai funcionar igual...