diff --git a/Behavioral/Observer/Tests/ObserverTest.php b/Behavioral/Observer/Tests/ObserverTest.php index 6a3f369..c263997 100644 --- a/Behavioral/Observer/Tests/ObserverTest.php +++ b/Behavioral/Observer/Tests/ObserverTest.php @@ -5,65 +5,16 @@ namespace DesignPatterns\Behavioral\Observer\Tests; use DesignPatterns\Behavioral\Observer\User; use DesignPatterns\Behavioral\Observer\UserObserver; -/** - * ObserverTest tests the Observer pattern. - */ class ObserverTest extends \PHPUnit_Framework_TestCase { - protected $observer; - - protected function setUp() + public function testChangeInUserLeadsToUserObserverBeingNotified() { - $this->observer = new UserObserver(); - } + $observer = new UserObserver(); - /** - * Tests the notification. - */ - public function testNotify() - { - $this->expectOutputString('DesignPatterns\Behavioral\Observer\User has been updated'); - $subject = new User(); + $user = new User(); + $user->attach($observer); - $subject->attach($this->observer); - $subject->property = 123; - } - - /** - * Tests the subscribing. - */ - public function testAttachDetach() - { - $subject = new User(); - $reflection = new \ReflectionProperty($subject, 'observers'); - - $reflection->setAccessible(true); - /** @var \SplObjectStorage $observers */ - $observers = $reflection->getValue($subject); - - $this->assertInstanceOf('SplObjectStorage', $observers); - $this->assertFalse($observers->contains($this->observer)); - - $subject->attach($this->observer); - $this->assertTrue($observers->contains($this->observer)); - - $subject->detach($this->observer); - $this->assertFalse($observers->contains($this->observer)); - } - - /** - * Tests the update() invocation on a mockup. - */ - public function testUpdateCalling() - { - $subject = new User(); - $observer = $this->createMock('SplObserver'); - $subject->attach($observer); - - $observer->expects($this->once()) - ->method('update') - ->with($subject); - - $subject->notify(); + $user->changeEmail('foo@bar.com'); + $this->assertCount(1, $observer->getChangedUsers()); } } diff --git a/Behavioral/Observer/User.php b/Behavioral/Observer/User.php index 0d2a817..6fd58d4 100644 --- a/Behavioral/Observer/User.php +++ b/Behavioral/Observer/User.php @@ -3,60 +3,42 @@ namespace DesignPatterns\Behavioral\Observer; /** - * Observer pattern : The observed object (the subject). - * - * The subject maintains a list of Observers and sends notifications. + * User implements the observed object (called Subject), it maintains a list of observers and sends notifications to + * them in case changes are made on the User object */ class User implements \SplSubject { /** - * user data. - * - * @var array + * @var string */ - protected $data = array(); + private $email; /** - * observers. - * * @var \SplObjectStorage */ - protected $observers; + private $observers; public function __construct() { $this->observers = new \SplObjectStorage(); } - /** - * attach a new observer. - * - * @param \SplObserver $observer - * - * @return void - */ public function attach(\SplObserver $observer) { $this->observers->attach($observer); } - /** - * detach an observer. - * - * @param \SplObserver $observer - * - * @return void - */ public function detach(\SplObserver $observer) { $this->observers->detach($observer); } - /** - * notify observers. - * - * @return void - */ + public function changeEmail(string $email) + { + $this->email = $email; + $this->notify(); + } + public function notify() { /** @var \SplObserver $observer */ @@ -64,21 +46,4 @@ class User implements \SplSubject $observer->update($this); } } - - /** - * Ideally one would better write setter/getter for all valid attributes and only call notify() - * on attributes that matter when changed. - * - * @param string $name - * @param mixed $value - * - * @return void - */ - public function __set($name, $value) - { - $this->data[$name] = $value; - - // notify the observers, that user has been updated - $this->notify(); - } } diff --git a/Behavioral/Observer/UserObserver.php b/Behavioral/Observer/UserObserver.php index f2673ba..243e740 100644 --- a/Behavioral/Observer/UserObserver.php +++ b/Behavioral/Observer/UserObserver.php @@ -2,19 +2,28 @@ namespace DesignPatterns\Behavioral\Observer; -/** - * class UserObserver. - */ class UserObserver implements \SplObserver { /** - * This is the only method to implement as an observer. - * It is called by the Subject (usually by SplSubject::notify() ). + * @var User[] + */ + private $changedUsers = []; + + /** + * It is called by the Subject, usually by SplSubject::notify() * * @param \SplSubject $subject */ public function update(\SplSubject $subject) { - echo get_class($subject).' has been updated'; + $this->changedUsers[] = clone $subject; + } + + /** + * @return User[] + */ + public function getChangedUsers(): array + { + return $this->changedUsers; } } diff --git a/Behavioral/Observer/uml/Observer.uml b/Behavioral/Observer/uml/Observer.uml index 0e5ddef..b74d770 100644 --- a/Behavioral/Observer/uml/Observer.uml +++ b/Behavioral/Observer/uml/Observer.uml @@ -1,27 +1,26 @@ - - - PHP - \DesignPatterns\Behavioral\Observer\User - - \DesignPatterns\Behavioral\Observer\UserObserver - \DesignPatterns\Behavioral\Observer\User - \SplSubject - - - - - - - - - - - - Fields - Constants - Constructors - Methods - - private - - + + + PHP + \DesignPatterns\Behavioral\Observer\UserObserver + + \DesignPatterns\Behavioral\Observer\UserObserver + \SplObserver + \DesignPatterns\Behavioral\Observer\User + + + + + + + + + + + + Fields + Constants + Methods + + private + + diff --git a/Behavioral/Observer/uml/uml.png b/Behavioral/Observer/uml/uml.png index 0300bd4..3eff464 100644 Binary files a/Behavioral/Observer/uml/uml.png and b/Behavioral/Observer/uml/uml.png differ diff --git a/Behavioral/Observer/uml/uml.svg b/Behavioral/Observer/uml/uml.svg index 09c79c1..44f3c60 100644 --- a/Behavioral/Observer/uml/uml.svg +++ b/Behavioral/Observer/uml/uml.svg @@ -1,310 +1,649 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - data - - - - - - - - - - observers - - - - - - - - - - - - attach(observer) - - - - - - - - - detach(observer) - - - - - - - - - notify() - - - - - - - - - __set(name, value) - - - - - - - - - - - - - User - - - User - - - - - - - - - - - - - - - - - - update(subject) - - - - - - - - - - - - - UserObserver - - - UserObserver - - - - - - - - - - - - - - - - - - attach(observer) - - - - - - - - - detach(observer) - - - - - - - - - notify() - - - - - - - - - - - - - SplSubject - - - SplSubject - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + changedUsers + + + + + + + + + + + + + + + + update(subject) + + + + + + + + + + + + + getChangedUsers() + + + + + + + + + + + + + UserObserver + + + UserObserver + + + + + + + + + + + + + + + + + + + + + + changedUsers + + + + + + + + + + + + + + + + + + + update(subject) + + + + + + + + + + + + + + + + getChangedUsers() + + + + + + + + + + + + + UserObserver + + + UserObserver + + + + + + + + + + + + + + + + + + + + + + update(subject) + + + + + + + + + + + + + SplObserver + + + SplObserver + + + + + + + + + + + + + + + + + + + + + + update(subject) + + + + + + + + + + + + + SplObserver + + + SplObserver + + + + + + + + + + + + + + + + + + + + + + + + + email + + + + + + + + + + + + + + + + observers + + + + + + + + + + + + + + + + attach(observer) + + + + + + + + + + + + + detach(observer) + + + + + + + + + + + + + changeEmail(email) + + + + + + + + + + + + + notify() + + + + + + + + + + + + + User + + + User + + + + + + + + + + + + + + + + + + + + + + email + + + + + + + + + + + + + + + + observers + + + + + + + + + + + + + + + + + + + attach(observer) + + + + + + + + + + + + + + + + detach(observer) + + + + + + + + + + + + + + + + changeEmail(email) + + + + + + + + + + + + + + + + notify() + + + + + + + + + + + + + User + + + User + + + + + + + + +