• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

PHP观察者模式

php 搞代码 3年前 (2022-01-23) 20次浏览 已收录 0个评论

概念

观察者模式属于行为模式,是定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。

当一个对象状态发生改变后,会影响到其他几个对象的改变,这时候可以用观察者模式。

观察者模式符合接口隔离原则,实现了对象之间的松散耦合。

别名

发布-订阅<Subscribe>模式

模型-视图<View>模式

源-收听者<Listener>模式

从属者模式

角色

抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。

具体主题(ConcreteSubject):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。

抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。

具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。

UML图

代码

示例代码

在PHP SPL中已经提供SplSubject和SqlOberver接口,源码如下:

/** * The <b>SplSubject</b> interface is used alongside * <b>SplObserver</b> to implement the Observer Design<b style="color:transparent">本文来源gao@!dai!ma.com搞$$代^@码!网!</b><strong>搞gaodaima代码</strong> 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);}

下面我们根据这两个spl接口,写自己的代码:

<?phpheader('Content-type:text/html;charset=utf-8');/** * 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 . '<br>';    }    /**     * 设置积分     *     * @param $integral     */    public function setIntegral($integral)    {        echo "积分量加" . $integral . '<br>';    }}/** * 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();

运行结果

数据量加10
积分量加10
积分量加10

优点和缺点

优点

观察者和主题之间的耦合度较小;

支持广播通信;

缺点

由于观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。这可能会引起意外的更新。

适用场景

当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。

当对一个对象的改变需要同时改变其它对象,而不知道具体有多少个对象待改变。

当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换句话说,你不希望这些对象是紧密耦合的。


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:PHP观察者模式

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址