Is the below a good solution for an observer to monitor multiple subjects. My only fear is that if an observer was monitoring a wide range of subjects then the update method could get quite large checking each instance to see what type it is but I can't think of another way to implement this:
Journalist Subject
class Journalist implements SplSubject {
protected $observers;
protected $name;
protected $story;
public function __construct( $name ) {
$this->name = $name;
$this->observers = new SplObjectStorage();
}
public function attach( SplObserver $observer ) {
$this->observers->attach( $observer );
}
public function detach( SplObserver $observer ) {
$this->observers->detach( $observer );
}
public function notify() {
foreach( $this->observers as $observer ) {
$observer->update( $this );
}
}
public function addStory( $story ) {
$this->story = $story;
$this->notify();
}
public function getStory() {
return $this->story;
}
public function addName( $name ) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
Website Subject
class Website implements SplSubject {
protected $observers;
protected $website;
protected $webPage;
public function __construct( $website ) {
$this->website = $website;
$this->observers = new SplObjectStorage();
}
public function attach( SplObserver $observer ) {
$this->observers->attach( $observer );
}
public function detach( SplObserver $observer ) {
$this->observers->detach( $observer );
}
public function notify() {
foreach( $this->observers as $observer ) {
$observer->update( $this );
}
}
public function addWebPage( $webPage ) {
$this->webPage = $webPage;
$this->notify();
}
public function getWebPage() {
return $this->webPage;
}
public function addWebsite( $website ) {
$this->website = $website;
}
public function getWebsite() {
return $this->website;
}
}
The Sun Observer
class TheSun implements SplObserver {
public function update( SplSubject $observable ) {
if( $observable instanceof Journalist )
echo __CLASS__ . ' noticed that the journalist ' . $observable->getName() . ' said: ' . $observable->getStory() . '<br />';
if( $observable instanceof Website )
echo __CLASS__ . ' noticed that the website ' . $observable->getWebsite() . ' uploaded a page to: ' . $observable->getWebPage() . '<br />';
}
}
The Mirror Observer
class TheMirror implements SplObserver {
public function update( SplSubject $observable ) {
if( $observable instanceof Journalist )
echo __CLASS__ . ' noticed that the journalist ' . $observable->getName() . ' said: ' . $observable->getStory() . '<br />';
if( $observable instanceof Website )
echo __CLASS__ . ' noticed that the website ' . $observable->getWebsite() . ' uploaded a page to: ' . $observable->getWebPage() . '<br />';
}
}
The Guardian Observer
class TheGuardian implements SplObserver {
public function update( SplSubject $observable ) {
if( $observable instanceof Journalist )
echo __CLASS__ . ' noticed that the journalist ' . $observable->getName() . ' said: ' . $observable->getStory() . '<br />';
if( $observable instanceof Website )
echo __CLASS__ . ' noticed that the website ' . $observable->getWebsite() . ' uploaded a page to: ' . $observable->getWebPage() . '<br />';
}
}
Code
$Journalist = new Journalist( 'John' );
$Website = new Website( 'Stack Overflow' );
$TheSun = new TheSun;
$TheMirror = new TheMirror;
$TheGuardian = new TheGuardian;
$Journalist->attach( $TheSun );
$Journalist->attach( $TheMirror );
$Journalist->attach( $TheGuardian );
$Website->attach( $TheSun );
$Website->attach( $TheMirror );
$Website->attach( $TheGuardian );
$Journalist->addStory( 'Knock, Knock' );
$Website->addWebPage( 'http://www.hello.com' );
$Journalist->detach( $TheSun );
$Journalist->detach( $TheMirror );
$Website->detach( $TheGuardian );
$Journalist->addStory( 'Whos There?' );
$Website->addWebPage( 'http://www.goodbye.com' );
The code should run exactly as is above. Any advice would be very welcome.
A second question I have is what if I wanted to notify the observers of more than one different action, for example some services might want to know in the example above if a Website or Journalists name has changed separately to if they have posted a new article, how could this be best accomplished?