This is a PHP implementation of the Java Observer/Observable classes.
Observable.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | <?php /** * Observable * * @author kenny */ class Observable { private $changed = false; private $observers = array(); public function addObserver(Observer $o) { if($o == null) { throw new NullPointerException(); } $contains = 0; foreach($this->observers as $observer) { if($o === $observer) { $contains = true; break; } } if(!$contains) { $this->observers[] = $o; } } public function deleteObserver(Observer $o) { for($i = 0; $i < count($this->observers); $i++) { if($this->observers[$i] == $o) { unset($this->observers[$i]); } } $observers = array(); foreach($this->observers as $observer) { $observers[] = $observer; } $this->observers = $observers; } public function notifyObservers($object = null) { if(!$this->changed) { return; $this->clearChanged(); } foreach($this->observers as $ob) { $ob->update($this, $object); } } public function deleteObservers() { $this->observers = array(); } protected function setChanged() { $this->changed = true; } protected function clearChanged() { $this->changed = false; } public function hasChanged() { return $this->changed; } public function countObservers() { return count($this->observers); } } ?> |
Observer.php
1 2 3 4 5 6 7 8 9 10 11 | <?php /** * * @author kenny */ interface Observer { public function update(Observable $o, $object); } ?> |
A Unit test (using SimpleTest)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | <?php define('SIMPLE_TEST', '../simpletest/'); require_once(SIMPLE_TEST . 'unit_tester.php'); require_once(SIMPLE_TEST . 'reporter.php'); require_once('Observable.php'); require_once('Observer.php'); class MockObservable extends Observable { public $object = null; public function set($object) { $this->object = $object; } public function setAndNotify($object) { $this->object = $object; $this->setChanged(); $this->notifyObservers($object); } } class MockObserver implements Observer { public $observed = null; public function update(Observable $o, $observed) { $this->observed = $observed; } } class ObserverTest extends UnitTestCase { public function setUp() { } public function test() { $observer = new MockObserver(); $observable = new MockObservable(); // test defaults $this->assertNull($observer->observed); $this->assertNull($observable->object); $this->assertFalse($observable->hasChanged()); $this->assertEqual($observable->countObservers(), 0); // test add $observable->addObserver($observer); $this->assertEqual($observable->countObservers(), 1); // test to not add duplicate observers $observable->addObserver($observer); $this->assertEqual($observable->countObservers(), 1); $observer2 = new MockObserver(); $observable->addObserver($observer2); $this->assertEqual($observable->countObservers(), 2); $observable->deleteObserver($observer2); $this->assertEqual($observable->countObservers(), 1); // test delete $observable->deleteObserver($observer); $this->assertEqual($observable->countObservers(), 0); $observable->addObserver($observer); $observable->set(10); // test not notfiy unless setChagnged() has been called $observable->notifyObservers(); $this->assertNull($observer->observed); // test notify $observable->setAndNotify(10); $this->assertEqual($observer->observed, 10); } } ?> |

Posted in
Tags: 
