Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Galera, eu vi algumas coisas mas não consegui entender como o pattern Observer se aplica no MVC. Poderiam me dar um exemplo (pode ser bem simples) ou até mesmo tentar me explicar. Obrigado :)
O uso mais comum que vi até agora para web é em forma de manipuladores de evento (Event Handler/Manager/Dispatcher), alguns frameworks utilizam no core para a chamada de rotinas internas e passagem de parâmetros entre os eventos.. a utilidade disso é poder adicionar ações e desconhecer o momento em que elas acontecem, e você ainda faz a chamada da rotina sem saber quais e quantas ações fazem parte da rotina.
Em geral, server-side events são uma implementação do padrão [inline]Mediator[/inline], não do [inline]Observer[/inline].
Poderiam me dar exemplos desses eventos?
Em geral, server-side events são uma implementação do padrão Mediator, não do Observer.
Mas o Mediator não é basicamente um Observer com possibilidade de engatilhamento manual?
Posso ter me equivocado com os padrões, mas também é possível criar eventos sem fugir do padrão Observer, e como questionado pelo Bruno e eu penso da mesma forma, o Mediator não deixa de ser um "Observer melhorado".
Observer: o objeto observado agrega seus observadores e o mesmo gerência a lista e decide quando serão notificados, geralmente quando um evento ocorre (mudança de estado).
Mediator: a decisão de quando os observadores serão notificados acontece em meio externo, portanto ele não tem conhecimento do objeto observado e nem da lista de observadores..
Gabriel talvez você já tenha visto exemplos do padrão Observer bem parecidos na internet, mas enfim vamos lá:
interface Observer {
public function update(Subject $s);
}
interface Subject {
public function attach(Observer $o);
public function detach(Observer $o);
public function notify();
}
class Person implements Subject {
/**
* @var Observer[]
*/
private $observers = [];
private $name;
public function attach(Observer $o) {
$this->observers[] = $o;
}
public function detach(Observer $o) {
$key = array_search($o, $this->observers);
if ($key !== false) {
unset($this->observers[$key]);
}
}
public function notify() {
foreach ($this->observers as $o) {
$o->update($this);
}
}
public function setName($name) {
$this->name = $name;
$this->notify();
}
public function getName() {
return $this->name;
}
}
class PersonLogger implements Observer {
public function update(Subject $s) {
$this->write('Person changed to: ' . $s->getName());
}
public function write($log) {
echo $log;
}
}
$person = new Person();
$person->attach(new PersonLogger());
$person->setName('José');
$person->setName('Maria');
Saída:
Person changed to: José
Person changed to: Maria
O exemplo é simples, neste contexto sempre que o nome da pessoa for alterado (evento) os observadores (listeners) serão notificados, no caso temos apenas um observador..PersonLogger, quando o mesmo é notificado ele apenas gera um log.
Um outro exemplo de uma implementação simples do Mediator usando callables:
class EventHandler {
private $listeners = array();
public function attach($name, $listener) {
if (!is_callable($listener)) {
throw new InvalidArgumentException('Listener is not callable');
}
$this->listeners[$name][] = $listener;
}
public function trigger($name) {
if (!isset($this->listeners[$name])) {
return;
}
foreach ($this->listeners[$name] as $listeners) {
call_user_func($listeners);
}
}
}
$events = new EventHandler();
$events->attach('say', function() {
echo 'Say something';
});
$events->attach('say', function() {
echo 'Say hello';
});
$events->trigger('say');
Saída:
Say something
Say hello
Este exemplo não é um exemplo real mas também é simples de se entender. É possível também personalizar a implementação adicionando prioridade de execução dos eventos, passagem de parâmetros e etc.. O Mediator também proporciona desacoplamento entre classes, sendo que poderia também customizar rotinas por exemplo, já que você poderia ter um Mediator disponível para toda sua aplicação e adicionar ou disparar eventos quando quiser.
Acho que entendi, mesmo estando um pouco perdido no Mediator. :natallaugh:
Mas o Mediator não é basicamente um Observer com possibilidade de engatilhamento manual?
A diferença entre ambos é o nível de acoplamento. Com o [inline]Observer[/inline], todo listener deve ser associado ao observável em questão. A chamada do método [inline]notify[/inline] dentro do observável fica a seu critério. Dessa forma, fica meio difícil pensar em eventos, já que não existe algo que os defina exatamente.
Um exemplo clássico de mediator é o DOM:
document.getElementById('my_id').addEventListener('click', function() {
// do something...
});
document.getElementById('my_id').addEventListener('dblclick', function() {
// do other stuff...
});
Fica bem definido que quando houver um clique, o callback deve ser chamado. Com um [inline]Observer[/inline] em sua forma canônica, é como se existe apenas um tipo de "evento" e o workarround para isso são condicionais:
class MySubject {
public function notify($event) {
switch($event) {
case 'evt1':
foreach ($this->observers as $obs) {
$this->updateEvt1($this->state);
}
break;
case 'evt2':
foreach ($this->observers as $obs) {
$this->updateEvt2($this->state);
}
break;
}
}
public function someMethod() {
// do stuff...
$this->notify('evt1');
}
public function otherMethod() {
// do stuff...
$this->notify('evt2');
}Resumindo: um Observer/Subject não será suficiente quando houver mais de um tipo de evento e quando quisermos que o acoplamento entre ambas as partes seja baixo. Para estes casos, usamos Mediator.
Nota: ambos os patterns são um subconjunto (especialização) de um "superpattern" chamado Publisher/Subscriber.
É difícil aplicar Observer no MVC p/ web.
Se quiser algum exemplo desktop, posso mostrar algo.