【一】模式定义

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

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

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

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

【二】UML类图

【三】示例代码

User.php

namespace 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

namespace DesignPatterns\Behavioral\Observer;

/**

* UserObserver 类(观察者对象)

*/

class UserObserver implements \SplObserver

{

/**

* 观察者要实现的唯一方法

* 也是被 Subject 调用的方法

*

* @param \SplSubject $subject

*/

public function update(\SplSubject $subject)

{

echo get_class($subject) . ' has been updated';

}

}

【四】测试代码

Tests/ObserverTest.php

namespace 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();

}

}

【五】总结

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

观察者设计模式 php,PHP设计模式 - 观察者模式相关推荐

  1. Javascript乱弹设计模式系列(1) - 观察者模式(Observer)

    前言 博客园谈设计模式的文章很多,我也受益匪浅,包括TerryLee.吕震宇等等的.NET设计模式系列文章,强烈推荐.对于我,擅长于前台代码的开发,对于设计模式也有一定的了解,于是我想结合Javasc ...

  2. c++ 设计模式_设计模式行为型:观察者模式(ObserverPattern)

    定义对象之间的一种一对多依赖关系,使得每一个对象发生状态的变化时,其相关依赖对象皆得到通知并被自动更新,又称为发布-订阅(Publish/Subscribe)模式.模型-视图(Model/View)模 ...

  3. C#设计模式之十六观察者模式(Observer Pattern)【行为型】

    C#设计模式之十六观察者模式(Observer Pattern)[行为型] 原文:C#设计模式之十六观察者模式(Observer Pattern)[行为型] 一.引言 今天是2017年11月份的最后一 ...

  4. 行为型设计模式(4)—— 观察者模式(Observer Pattern)

    文章目录 1.概述 2.实例 2.1 丑陋的设计 2.2 使用观察者模式 3.应用场景 4.优缺点 5.小结 参考文献 1.概述 使用设计模式可以提高代码的可复用性.可扩充性和可维护性.观察者模式(O ...

  5. Unity游戏设计模式(二)观察者模式(Observer Pattern)

    最近看游戏设计模式,当看到观察者模式时被搞得云里雾里的,什么观察者,被观察者,抽象观察者,抽象被观察者.听着这些词就觉得可怕,其实理解以后还是比较简单的. 当我们玩游戏时,经常会出现一些事件,而这个事 ...

  6. JavaScript设计模式——Observe模式(观察者模式)

    通常一个优秀的项目,会使用到很多的设计模式,这些设计模式在我们的解决方案中,会起到十分重要的作用,它的存在,能使项目的结构更加简洁.清晰.易于理解. 所以了解常用的设计模式,会让我们在日常开发更加得心 ...

  7. php设计模式课程---4、观察者模式的好处是什么

    php设计模式课程---4.观察者模式的好处是什么 一.总结 一句话总结: 方便选择之后去控制监听的板块数:比如选择男士之后,我可以决定监听广告里面的第二和第三板块. 1.为什么有观察者模式? 错误理 ...

  8. 设计模式混编:观察者模式+中介者模式

    针对变化万千的业务需求,采用合适的设计模式是可以轻松应对的. 本文将探索多种优秀设计模式的混编来解决复杂场景的问题,实现1+1>2的效果.应用实践离不开基础,所以文章将以基本概念.设计初衷出发, ...

  9. java 设计模式 示例_Java设计模式–示例教程

    java 设计模式 示例 Design Patterns are very popular among software developers. A design pattern is a well- ...

  10. java设计模式:23种设计模式及其源代码演示实现

    java23种设计模式及其源代码演示实现 博主在CSDN已有三年,之前一直在看贴,受益颇多,不可多得的一个良好的学习平台,这一次,博主给大家分享一份传说中的java设计模式,源代码与其实现全部都有,希 ...

最新文章

  1. opencv-mediapipe手部关键点识别
  2. CleanMyMac扩展管理功能
  3. mysql gtid 搭建主从_MySQL5.7 - 基于GTID复制模式搭建主从复制
  4. 找二叉树中给定元素的的左孩子结点_LeetCode高频题:二叉树(五)
  5. Java黑皮书课后题第6章:6.1(数学:五角数)一个五角数被定义为n*(3*n-1)/2,其中n=1、2…。所以开始的几个数字就是1、5、12、22…,编写具有以下方法头的方法,返回一个五角数
  6. c# 文件流读写文件
  7. Spark学习笔记——在集群上运行Spark
  8. 关于 SAP CRM 订单抬头级别的 Text 无法编辑的问题分析
  9. php查询数据方法,php查询数据库的方法
  10. python 定义字符串变量_Python变量和字符串详解
  11. Laravel源码解析之事件系统
  12. 剑指offer——python【第16题】合并两个有序链表
  13. java发牌_Java实现洗牌发牌的方法
  14. C++ 迭代器 删除(erase)插入(insert)之后失效
  15. t检验的显著性p值python_Python P值
  16. [量化学院]基于协整的配对交易
  17. 服务器XP系统打印机共享设置,windowsxp系统打印机共享设置方法介绍
  18. ipad上写代码???阿里云+vscode-server助你一臂之力
  19. 框架-Laraver
  20. 上海交大PMP——职场妈妈的学习干货分享

热门文章

  1. Android实现自定义的 时间日期 控件
  2. Centos-Server-Nginx服务(编译安装)
  3. 【BIOS大全】释义+设置+精解+释疑————玩转电脑必备工具帖(8)
  4. 贪婪算法近似集合覆盖问题的解
  5. for update造成的Oracle锁表与解锁
  6. [Asp.net]SignalR实现实时日志监控
  7. 程序包org.springframework.stereotype不存在,解决办法
  8. Splunk和ElasticSearch深度对比解析
  9. thinkphp 5 stdClass Call to undefined
  10. Linux下创建用于并指定该用户的主目录和相关权限