目录
1、模式定义
2、UML类图
3、示例代码
4、测试代码
5、总结
首页 后端开发 php教程 PHP 设计模式系列 -- 观察者模式(Observer)

PHP 设计模式系列 -- 观察者模式(Observer)

Jun 23, 2016 pm 01:19 PM

1、模式定义

观察者模式有时也被称作发布/订阅模式,该模式用于为对象实现发布/订阅功能:一旦主体对象状态发生改变,与之关联的观察者对象会收到通知,并进行相应操作。

将一个系统分割成一个一些类相互协作的类有一个不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。观察者就是解决这类的耦合关系的。

消息队列系统、事件都使用了观察者模式。

PHP 为观察者模式定义了两个接口:SplSubject 和SplObserver。SplSubject 可以看做主体对象的抽象,SplObserver 可以看做观察者对象的抽象,要实现观察者模式,只需让主体对象实现 SplSubject ,观察者对象实现 SplObserver,并实现相应方法即可。

2、UML类图

3、示例代码

User.php

<?phpnamespace DesignPatterns\Behavioral\Observer;/** * 观察者模式 : 被观察对象 (主体对象) * * 主体对象维护观察者列表并发送通知 * */class User implements \SplSubject{    /**     * user data     *     * @var array     */    protected $data = array();    /**     * observers     *     * @var \SplObjectStorage     */    protected $observers;        public function __construct()    {        $this->observers = new \SplObjectStorage();    }    /**     * 附加观察者     *     * @param \SplObserver $observer     *     * @return void     */    public function attach(\SplObserver $observer)    {        $this->observers->attach($observer);    }    /**     * 取消观察者     *     * @param \SplObserver $observer     *     * @return void     */    public function detach(\SplObserver $observer)    {        $this->observers->detach($observer);    }    /**     * 通知观察者方法     *     * @return void     */    public function notify()    {        /** @var \SplObserver $observer */        foreach ($this->observers as $observer) {            $observer->update($this);        }    }    /**     *     * @param string $name     * @param mixed  $value     *     * @return void     */    public function __set($name, $value)    {        $this->data[$name] = $value;        // 通知观察者用户被改变        $this->notify();    }}
登录后复制

UserObserver.php

<?phpnamespace DesignPatterns\Behavioral\Observer;/** * UserObserver 类(观察者对象) */class UserObserver implements \SplObserver{    /**     * 观察者要实现的唯一方法     * 也是被 Subject 调用的方法     *     * @param \SplSubject $subject     */    public function update(\SplSubject $subject)    {        echo get_class($subject) . ' has been updated';    }}
登录后复制

4、测试代码

Tests/ObserverTest.php

<?phpnamespace DesignPatterns\Behavioral\Observer\Tests;use DesignPatterns\Behavioral\Observer\UserObserver;use DesignPatterns\Behavioral\Observer\User;/** * ObserverTest 测试观察者模式 */class ObserverTest extends \PHPUnit_Framework_TestCase{    protected $observer;    protected function setUp()    {        $this->observer = new UserObserver();    }    /**     * 测试通知     */    public function testNotify()    {        $this->expectOutputString('DesignPatterns\Behavioral\Observer\User has been updated');        $subject = new User();        $subject->attach($this->observer);        $subject->property = 123;    }    /**     * 测试订阅     */    public function testAttachDetach()    {        $subject = new User();        $reflection = new \ReflectionProperty($subject, 'observers');        $reflection->setAccessible(true);        /** @var \SplObjectStorage $observers */        $observers = $reflection->getValue($subject);        $this->assertInstanceOf('SplObjectStorage', $observers);        $this->assertFalse($observers->contains($this->observer));        $subject->attach($this->observer);        $this->assertTrue($observers->contains($this->observer));        $subject->detach($this->observer);        $this->assertFalse($observers->contains($this->observer));    }    /**     * 测试 update() 调用     */    public function testUpdateCalling()    {        $subject = new User();        $observer = $this->getMock('SplObserver');        $subject->attach($observer);        $observer->expects($this->once())            ->method('update')            ->with($subject);        $subject->notify();    }}
登录后复制

5、总结

观察者模式解除了主体和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 周前 By 尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 周前 By 尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热门文章标签

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

11个最佳PHP URL缩短脚本(免费和高级) 11个最佳PHP URL缩短脚本(免费和高级) Mar 03, 2025 am 10:49 AM

11个最佳PHP URL缩短脚本(免费和高级)

在Laravel中使用Flash会话数据 在Laravel中使用Flash会话数据 Mar 12, 2025 pm 05:08 PM

在Laravel中使用Flash会话数据

构建具有Laravel后端的React应用程序:第2部分,React 构建具有Laravel后端的React应用程序:第2部分,React Mar 04, 2025 am 09:33 AM

构建具有Laravel后端的React应用程序:第2部分,React

简化的HTTP响应在Laravel测试中模拟了 简化的HTTP响应在Laravel测试中模拟了 Mar 12, 2025 pm 05:09 PM

简化的HTTP响应在Laravel测试中模拟了

php中的卷曲:如何在REST API中使用PHP卷曲扩展 php中的卷曲:如何在REST API中使用PHP卷曲扩展 Mar 14, 2025 am 11:42 AM

php中的卷曲:如何在REST API中使用PHP卷曲扩展

在Codecanyon上的12个最佳PHP聊天脚本 在Codecanyon上的12个最佳PHP聊天脚本 Mar 13, 2025 pm 12:08 PM

在Codecanyon上的12个最佳PHP聊天脚本

宣布 2025 年 PHP 形势调查 宣布 2025 年 PHP 形势调查 Mar 03, 2025 pm 04:20 PM

宣布 2025 年 PHP 形势调查

Laravel中的通知 Laravel中的通知 Mar 04, 2025 am 09:22 AM

Laravel中的通知

See all articles