observers = Array(); } // end :: __construct /** * Chama o método update() usando a referência de cada * observador registrado. Usado por filhas desta classe * * @access protected * @param void * @return void */ protected function notify () { $observers = count( $this->observers ); for ($i=0;$i<$observers;$i++) { $this->observers[$i]->update(); } } // end :: notify /** * Registra a referência para um objeto Observer * * @access public * @param object $observer Objeto a ser notificado * @return void */ public function attach ( & $observer ) { $this->observers[] = & $observer; $observer->setSubject( & $this ); } // end :: attach /** * Remove a referência de um objeto Observer * * @access public * @param object $observer Objeto a ser removido da lista * @return void */ public function detach( & $observer ) { if( in_array( $observer, $this->observers ) ) { $key = array_search( $observer, $this->observers ); unset( $this->observers[$key] ); } } // end :: detach /** * Retorna o valor atual da propriedade state * * @access public * @param void * @return mixed Conteúdo da propriedade state */ public function getState () { return $this->state; } //end :: getState /** * Atribui um valor para a propriedade state * * @access public * @param $state mixed Conteúdo a ser atribuído * @return void */ public function setState ( $state ) { $this->state = $state; } // end :: setState } // end :: Observable /** * Classe base "Observer" */ abstract class Observer { /** * @access protected * @var $subject Um filho da classe Observable que nós observaremos */ protected $subject; /** * Construtor da classe Observer * * @access public * @param $subject O objeto a ser observado (opcional) */ public function __construct ( & $subject = null ) { if( is_object( $subject ) ) { $this->setSubject( & $subject ); $subject->attach( $this ); } else $this->subject = null; } // end :: __construct /** * Guarda em subject uma referência para o objeto que está sendo * observado. * * Esta função pode ser chamada tanto pelo construtor da classe, ou * através do objeto observado, quando se chamar attach() * * @access public * @param object $subject Objeto observado */ public function setSubject( & $subject ) { $this->subject = & $subject; } // end :: setSubject /** * Método abstrato implemnetado por filhos para * responder a mudanças no objeto observado * * @abstract * @access public */ abstract public function update(); } // end :: Observer ////////////////////////////// // Exemplo: A observa B class A extends Observer { public function update() { // Este método é executado quando o Observado alterar // o estado. Aqui poderiam ser feitas outras coisas, tendo // ainda disponível o estado em getState() para se decidir // a ação a ser tomada. print "Classe A foi notificada! Mensagem passada: ".$this->subject->getState()."\n"; } } // end :: A class B extends Observable { public function acao() { // Este é um método que altera o estado do objeto, e portanto // deve notificar todos os seus observadores. print "Executando uma ação... \n"; $this->setState( "Classe B executou uma ação." ); // o observador terá acesso a isso! $this->notify(); } } // end :: B $b = new B(); // Objeto observado $a = new A(); // Objeto observador $b->attach( & $a ); // A passa a ser notificado de alterações em B (i.e., A passa a observar B) $b->acao(); // acao() em B notifica todos os observadores (A, no caso) $b->detach( & $a ); // Agora A não observa mais B $b->acao(); // acao() em B não notifica mais A ?>