Observer
Problématique
Comment prévenir un ensemble d’objets lorsqu’un autre objet est modifié?
Observer est l’objet qui souhaite être prévenu du changement d’état d’un autre objet
Observable (Sujet) est un objet capable de prévenir au autre objet lorsqu’il est modifié
Solution
L’objet Observer doit s’enregistrer auprès de l’objet Observable
class Memory implements SplSubject { const READ_OPERATION = 0 ; const WRITE_OPERATION = 1 ; private $data = array() ; private $observers = array() ; private $last_operation = null ; private $address = null ; private $value = null ; public function getLastOperation() { return $this->last_operation ; } public function getAddress() { return $this->address ; } public function getValue() { return $this->value ; } public function read($address) { $this->last_operation = self::READ_OPERATION ; $this->address = $address ; $this->value = isset($this->data[$address]) ? $this->data[$address] : 0 ; $this->notify() ; return $this->value ; } public function write($address, $value) { $this->last_operation = self::WRITE_OPERATION ; $this->address = $address ; $this->value = $value ; $this->data[$address] = $value ; $this->notify() ; } public function attach(SplObserver $observer) { if(in_array($observer, $this->observers)) return ; $this->observers[] = $observer ; } public function detach(SplObserver $observer) { $key = array_search($observer, $this->observers) ; if(is_null($key)) return ; unset($this->observers[$key]) ; } public function notify() { foreach($this->observers as $obs) { $obs->update($this) ; } } } class MemoryLog implements SplObserver { private $filename = '' ; public function __construct($filename) { $this->filename = $filename ; } public function update(SplSubject $subject) { file_put_contents( $this->filename, 'Last operation: ' . $subject->getLastOperation() . ' - address: ' . $subject->getAddress() . ' - value: ' . $subject->getValue() . "\r\n", FILE_APPEND ) ; } } class MemoryDisplayEvents implements SplObserver { public function update(SplSubject $subject) { echo $subject->getLastOperation() == Memory::READ_OPERATION ? 'read' : 'write' ; echo ' at ', $subject->getAddress(), ' : ', $subject->getValue(), '<br />' ; } } $mem = new Memory() ; $mem->attach(new MemoryLog('C:/mem.log')) ; $mem->attach(new MemoryDisplayEvents()) ; for($i = 0 ; $i < 50 ; $i++) { $address = rand(0,10) ; if(rand() % 2) { $mem->read($address) ; } else { $value = rand(0,255) ; $mem->write($address, $value) ; } }
Commentaires récents