Интерфейс SplSubject

(PHP 5 >= 5.1.0)

Введение

Интерфейс SplSubject используется совместно с SplObserver для реализации шаблона проектирования Наблюдатель (Observer).

Обзор интерфейсов

SplSubject {
/* Методы */
abstract public void attach ( SplObserver $observer )
abstract public void detach ( SplObserver $observer )
abstract public void notify ( void )
}

Содержание

Коментарии

<?php 

// Example implementation of Observer design pattern:

class MyObserver1 implements SplObserver {
    public function 
update(SplSubject $subject) {
        echo 
__CLASS__ ' - ' $subject->getName();
    }
}

class 
MyObserver2 implements SplObserver {
    public function 
update(SplSubject $subject) {
        echo 
__CLASS__ ' - ' $subject->getName();
    }
}

class 
MySubject implements SplSubject {
    private 
$_observers;
    private 
$_name;

    public function 
__construct($name) {
       
$this->_observers = new SplObjectStorage();
       
$this->_name $name;
    }

    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 
getName() {
        return 
$this->_name;
    }
}

$observer1 = new MyObserver1();
$observer2 = new MyObserver2();

$subject = new MySubject("test");

$subject->attach($observer1);
$subject->attach($observer2);
$subject->notify();

/* 
will output:

MyObserver1 - test
MyObserver2 - test
*/

$subject->detach($observer2);
$subject->notify();

/* 
will output:

MyObserver1 - test
*/

?>
2012-02-26 23:54:34
http://php5.kiev.ua/manual/ru/class.splsubject.html
Автор:
<?php
class Observable implements SplSubject
{
    private 
$storage;

    function 
__construct()
    {
       
$this->storage = new SplObjectStorage();
    }

    function 
attach(SplObserver $observer)
    {
       
$this->storage->attach($observer);
    }

    function 
detach(SplObserver $observer)
    {
       
$this->storage->detach($observer);
    }

    function 
notify()
    {
        foreach (
$this->storage as $obj) {
           
$obj->update($this);
        }
    }
   
//...
}

abstract class 
Observer implements SplObserver
{
    private 
$observable;

    function 
__construct(Observable $observable)
    {
       
$this->observable $observable;
       
$observable->attach($this);
    }

    function 
update(SplSubject $subject)
    {
        if (
$subject === $this->observable) {
           
$this->doUpdate($subject);
        }
    }

    abstract function 
doUpdate(Observable $observable);
}

class 
ConcreteObserver extends Observer
{
    function 
doUpdate(Observable $observable)
    {
       
//...
   
}
}

$observable = new Observable();
new 
ConcreteObserver($observable);
2013-05-07 13:37:44
http://php5.kiev.ua/manual/ru/class.splsubject.html
/**
 * Subject,that who makes news
 */
class Newspaper implements \SplSubject{
    private $name;
    private $observers = array();
    private $content;
   
    public function __construct($name) {
        $this->name = $name;
    }

    //add observer
    public function attach(\SplObserver $observer) {
        $this->observers[] = $observer;
    }
   
    //remove observer
    public function detach(\SplObserver $observer) {
       
        $key = array_search($observer,$this->observers, true);
        if($key){
            unset($this->observers[$key]);
        }
    }
   
    //set breakouts news
    public function breakOutNews($content) {
        $this->content = $content;
        $this->notify();
    }
   
    public function getContent() {
        return $this->content." (by {$this->name})";
    }
   
    //notify observers(or some of them)
    public function notify() {
        foreach ($this->observers as $value) {
            $value->update($this);
        }
    }
}

/**
 * Observer,that who recieves news
 */
class Reader implements SplObserver{
    private $name;
   
    public function __construct($name) {
        $this->name = $name;
    }
   
    public function update(\SplSubject $subject) {
        echo $this->name.' is reading breakout news <b>'.$subject->getContent().'</b><br>';
    }
}

//classes test
$newspaper = new Newspaper('Newyork Times');

$allen = new Reader('Allen');
$jim = new Reader('Jim');
$linda = new Reader('Linda');

//add reader
$newspaper->attach($allen);
$newspaper->attach($jim);
$newspaper->attach($linda);

//remove reader
$newspaper->detach($linda);

//set break outs
$newspaper->breakOutNews('USA break down!');

//=========output==========
//Allen is reading breakout news USA break down! (by Newyork Times)
//Jim is reading breakout news USA break down! (by Newyork Times)
2013-07-02 10:01:56
http://php5.kiev.ua/manual/ru/class.splsubject.html
For a few years, I've made a few attempts to understand the architecture behind the Subject/Observer pair. Recently I tried again. I just could not imagine why someone would design this in the way it is documented.  I mean, "what were they thinking?!", I thought. The if things outside of the Subject could tell it when to notify observers, that would completely break encapsulation. Because only the subject can know when events occur inside of it. And therefore, exposing `notify()` would be a huge violation to many principles of good OOP design.

However, I have come up with one scenario where this would be valid. That is, if the Subject represents a Hook, like in WordPress. For example, in an event system where events are invoked with a name or code, a Hook could represent a named event in the system, and by calling `notify()` from outside the dispatcher could notify observers. If this is the intended scenario, then the problems are mostly with naming: the name "Subject" implies that it is what is being observed, and the Observer pattern is different.
2019-04-01 21:57:49
http://php5.kiev.ua/manual/ru/class.splsubject.html

    Поддержать сайт на родительском проекте КГБ