Home >Backend Development >PHP Tutorial >PHP observer pattern

PHP observer pattern

高洛峰
高洛峰Original
2016-11-21 17:01:061694browse

Concept

The observer pattern is a behavioral pattern that defines a one-to-many dependency relationship between objects, so that when the state of an object changes, all objects that depend on it are notified and automatically refreshed.

When the state of an object changes, it will affect the changes of several other objects. At this time, the observer mode can be used.

The observer pattern complies with the interface isolation principle and achieves loose coupling between objects.

Alias

Publish-Subscribe> Pattern

Model-View Pattern

Source-Listener> Pattern

Slave Pattern

Role

Abstract Subject (Subject): It keeps references to all observer objects in a collection, and each subject can have any number of observers. The abstract theme provides an interface to add and remove observer objects.

Concrete Subject (ConcreteSubject): Store the relevant status in a specific observer object; when the internal status of the specific subject changes, a notification is sent to all registered observers.

Abstract Observer (Observer): Define an interface for all concrete observers and update themselves when notified by the topic.

Concrete Observer: Implement the update interface required by the abstract observer role in order to coordinate its own state with the subject state.

UML diagram

PHP observer pattern

Code

Sample code

The SplSubject and SqlOberver interfaces have been provided in PHP SPL. The source code is as follows:

/**
 * The <b>SplSubject</b> interface is used alongside
 * <b>SplObserver</b> to implement the Observer Design Pattern.
 * @link http://php.net/manual/en/class.splsubject.php
 */
interface SplSubject  {

        /**
         * Attach an SplObserver
         * @link http://php.net/manual/en/splsubject.attach.php
         * @param SplObserver $observer <p>
     * The <b>SplObserver</b> to attach.
         * </p>
         * @return void 
         * @since 5.1.0
         */
        public function attach (SplObserver $observer);

        /**
         * Detach an observer
         * @link http://php.net/manual/en/splsubject.detach.php
         * @param SplObserver $observer <p>
     * The <b>SplObserver</b> to detach.
         * </p>
         * @return void 
         * @since 5.1.0
         */
        public function detach (SplObserver $observer);

        /**
         * Notify an observer
         * @link http://php.net/manual/en/splsubject.notify.php
         * @return void 
         * @since 5.1.0
         */
        public function notify ();

}

/**
 * The <b>SplObserver</b> interface is used alongside
 * <b>SplSubject</b> to implement the Observer Design Pattern.
 * @link http://php.net/manual/en/class.splobserver.php
 */
interface SplObserver  {

        /**
         * Receive update from subject
         * @link http://php.net/manual/en/splobserver.update.php
         * @param SplSubject $subject <p>
     * The <b>SplSubject</b> notifying the observer of an update.
         * </p>
         * @return void 
         * @since 5.1.0
         */
        public function update (SplSubject $subject);

}

Now we write our own code based on these two spl interfaces:

<?php
header(&#39;Content-type:text/html;charset=utf-8&#39;);

/**
 * Class Subject 主题
 */
class Subject implements SplSubject
{
    private $_observers = [];

    /**
     * 实现添加观察者方法
     *
     * @param SplObserver $observer
     */
    public function attach(SplObserver $observer)
    {
        if (!in_array($observer, $this->_observers)) {
            $this->_observers[] = $observer;
        }
    }

    /**
     * 实现移除观察者方法
     *
     * @param SplObserver $observer
     */
    public function detach(SplObserver $observer)
    {
        if (false !== ($index = array_search($observer, $this->_observers))) {
            unset($this->_observers[$index]);
        }
    }

    /**
     * 实现提示信息方法
     */
    public function notify()
    {
        foreach ($this->_observers as $observer) {
            $observer->update($this);
        }
    }

    /**
     * 设置数量
     *
     * @param $count
     */
    public function setCount($count)
    {
        echo "数据量加" . $count . &#39;<br>&#39;;
    }

    /**
     * 设置积分
     *
     * @param $integral
     */
    public function setIntegral($integral)
    {
        echo "积分量加" . $integral . &#39;<br>&#39;;
    }

}

/**
 * Class Observer1 观察者一
 */
class Observer1 implements SplObserver
{
    public function update(SplSubject $subject)
    {
        $subject->setCount(10);
    }
}

/**
 * Class Observer2 观察者二
 */
class Observer2 implements SplObserver
{
    public function update(SplSubject $subject)
    {
        $subject->setIntegral(10);
    }
}


/**
 * Class Client 客户端
 */
class Client
{
    /**
     * 测试方法
     */
    public static function test()
    {
        // 初始化主题
        $subject = new Subject();
        // 初始化观察者一
        $observer1 = new Observer1();
        // 初始化观察者二
        $observer2 = new Observer2();
        // 添加观察者一
        $subject->attach($observer1);
        // 添加观察者二
        $subject->attach($observer2);
        // 消息提示
        $subject->notify();//输出:数据量加1 积分量加10
        // 移除观察者一
        $subject->detach($observer1);
        // 消息提示
        $subject->notify();//输出:数据量加1 积分量加10 积分量加10
    }
}

// 执行测试
Client::test();

Running results

The amount of data plus 10
The amount of points plus 10
The amount of points plus 10

Advantages and disadvantages

Advantages

The coupling between the observer and the subject is small;

Supports broadcast communication;

Disadvantages

Since the observer is not aware of the existence of other observers, it may not know the ultimate cost of changing the target. This may cause unexpected updates.

Applicable scenarios

When an abstract model has two aspects, one of which depends on the other.

When changes to one object require changes to other objects at the same time, you don’t know how many objects need to be changed.

When an object must notify other objects, it cannot assume who the other objects are. In other words, you don't want these objects to be tightly coupled.


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn