mirror of
https://github.com/DesignPatternsPHP/DesignPatternsPHP.git
synced 2025-07-30 19:50:12 +02:00
start a restructure
This commit is contained in:
14
Behavioral/Observer/README.md
Normal file
14
Behavioral/Observer/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Observer
|
||||
|
||||
## Purpose
|
||||
|
||||
To implement a publish/subscribe behaviour to an object, whenever a "Subject" object changes it's state, the attached
|
||||
"Observers" will be notified. It is used to shorten the amount of coupled objects and uses loose coupling instead.
|
||||
|
||||
## Examples
|
||||
|
||||
* a message queue system is observed to show the progress of a job in a GUI
|
||||
|
||||
## Note
|
||||
|
||||
PHP already defines two interfaces that can help to implement this pattern: SplObserver and SplSubject.
|
62
Behavioral/Observer/Test/ObserverTest.php
Normal file
62
Behavioral/Observer/Test/ObserverTest.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Tests\Observer;
|
||||
|
||||
use DesignPatterns\Observer\UserObserver;
|
||||
use DesignPatterns\Observer\User;
|
||||
|
||||
/**
|
||||
* ObserverTest tests the Observer pattern
|
||||
*/
|
||||
class ObserverTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
protected $observer;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->observer = new UserObserver();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the notification
|
||||
*/
|
||||
public function testNotify()
|
||||
{
|
||||
$this->expectOutputString('DesignPatterns\Observer\User has been updated');
|
||||
$subject = new User();
|
||||
|
||||
$subject->attach($this->observer);
|
||||
$subject->property = 123;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the subscribing
|
||||
*/
|
||||
public function testAttachDetach()
|
||||
{
|
||||
$subject = new User();
|
||||
$this->assertAttributeEmpty('observers', $subject);
|
||||
$subject->attach($this->observer);
|
||||
$this->assertAttributeNotEmpty('observers', $subject);
|
||||
$subject->detach($this->observer);
|
||||
$this->assertAttributeEmpty('observers', $subject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the update() invocation on a mockup
|
||||
*/
|
||||
public function testUpdateCalling()
|
||||
{
|
||||
$subject = new User();
|
||||
$observer = $this->getMock('SplObserver');
|
||||
$subject->attach($observer);
|
||||
|
||||
$observer->expects($this->once())
|
||||
->method('update')
|
||||
->with($subject);
|
||||
|
||||
$subject->notify();
|
||||
}
|
||||
|
||||
}
|
84
Behavioral/Observer/User.php
Normal file
84
Behavioral/Observer/User.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Observer;
|
||||
|
||||
/**
|
||||
* Observer pattern : The observed object (the subject)
|
||||
*
|
||||
* The subject maintains a list of Observers and sends notifications.
|
||||
*
|
||||
*/
|
||||
class User implements \SplSubject
|
||||
{
|
||||
/**
|
||||
* user data
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $data = array();
|
||||
|
||||
/**
|
||||
* observers
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $observers = array();
|
||||
|
||||
/**
|
||||
* attach a new observer
|
||||
*
|
||||
* @param \SplObserver $observer
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function attach(\SplObserver $observer)
|
||||
{
|
||||
$this->observers[] = $observer;
|
||||
}
|
||||
|
||||
/**
|
||||
* detach an observer
|
||||
*
|
||||
* @param \SplObserver $observer
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function detach(\SplObserver $observer)
|
||||
{
|
||||
$index = array_search($observer, $this->observers);
|
||||
|
||||
if (false !== $index) {
|
||||
unset($this->observers[$index]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* notify observers
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function notify()
|
||||
{
|
||||
/** @var SplObserver $observer */
|
||||
foreach ($this->observers as $observer) {
|
||||
$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();
|
||||
}
|
||||
}
|
20
Behavioral/Observer/UserObserver.php
Normal file
20
Behavioral/Observer/UserObserver.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\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() )
|
||||
*
|
||||
* @param \SplSubject $subject
|
||||
*/
|
||||
public function update(\SplSubject $subject)
|
||||
{
|
||||
echo get_class($subject) . ' has been updated';
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user