start a restructure

This commit is contained in:
Antonio Spinelli
2014-03-21 18:03:44 -03:00
parent b0b0d4a1a4
commit e59d70a0ac
180 changed files with 21 additions and 16 deletions

View 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.

View 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();
}
}

View 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();
}
}

View 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';
}
}