学习php设计模式 php实现观察者模式(Observer)


Posted in PHP onDecember 09, 2015

一、意图
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新【GOF95】
又称为发布-订阅(Publish-Subscribe)模式、模型-视图(Model-View)模式、源-监听(Source-Listener)模式、或从属者(Dependents)模式
二、观察者模式结构图

学习php设计模式 php实现观察者模式(Observer) 

三、观察者模式中主要角色
抽象主题(Subject)角色:主题角色将所有对观察者对象的引用保存在一个集合中,每个主题可以有任意多个观察者。抽象主题提供了增加和删除观察者对象的接口。
抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在观察的主题发生改变时更新自己。
具体主题(ConcreteSubject)角色:存储相关状态到具体观察者对象,当具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。
具体观察者(ConcretedObserver)角色:存储一个具体主题对象,存储相关状态,实现抽象观察者角色所要求的更新接口,以使得其自身状态和主题的状态保持一致。
四、观察者模式的优点和缺点
观察者模式的优点:
1、观察者和主题之间的耦合度较小;
2、支持广播通信;
观察者模式的缺点:
1、由于观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。这可能会引起意外的更新。
五、观察者模式适用场景
1、当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。
2、当对一个对象的改变需要同时改变其它对象,而不知道具体有多少个对象待改变。
3、当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换句话说,你不希望这些对象是紧密耦合的。
六、观察者模式与其它模式
中介者模式(Mediator):通过封装复杂的更新语义,ChangeManager充当目标和观察者之间的中介者。
单例模式(singleton模式):ChangeManager可使用Singleton模式来保证它是唯一的并且是可全局访问的。
七、观察者模式PHP示例

<?php
/**
 * 抽象主题角色
 */
interface Subject {
 
  /**
   * 增加一个新的观察者对象
   * @param Observer $observer
   */
  public function attach(Observer $observer);
 
  /**
   * 删除一个已注册过的观察者对象
   * @param Observer $observer
   */
  public function detach(Observer $observer);
 
  /**
   * 通知所有注册过的观察者对象
   */
  public function notifyObservers();
}
 
/**
 * 具体主题角色
 */
class ConcreteSubject implements Subject {
 
  private $_observers;
 
  public function __construct() {
    $this->_observers = array();
  }
 
  /**
   * 增加一个新的观察者对象
   * @param Observer $observer
   */
  public function attach(Observer $observer) {
    return array_push($this->_observers, $observer);
  }
 
  /**
   * 删除一个已注册过的观察者对象
   * @param Observer $observer
   */
  public function detach(Observer $observer) {
    $index = array_search($observer, $this->_observers);
    if ($index === FALSE || ! array_key_exists($index, $this->_observers)) {
      return FALSE;
    }
 
    unset($this->_observers[$index]);
    return TRUE;
  }
 
  /**
   * 通知所有注册过的观察者对象
   */
  public function notifyObservers() {
    if (!is_array($this->_observers)) {
      return FALSE;
    }
 
    foreach ($this->_observers as $observer) {
      $observer->update();
    }
 
    return TRUE;
  }
 
}
 
/**
 * 抽象观察者角色
 */
interface Observer {
 
  /**
   * 更新方法
   */
  public function update();
}
 
class ConcreteObserver implements Observer {
 
  /**
   * 观察者的名称
   * @var <type>
   */
  private $_name;
 
  public function __construct($name) {
    $this->_name = $name;
  }
 
  /**
   * 更新方法
   */
  public function update() {
    echo 'Observer', $this->_name, ' has notified.<br />';
  }
 
}
 
/**
 * 客户端
 */
class Client {
 
  /**
   * Main program.
   */
  public static function main() {
    $subject = new ConcreteSubject();
 
    /* 添加第一个观察者 */
    $observer1 = new ConcreteObserver('Martin');
    $subject->attach($observer1);
 
    echo '<br /> The First notify:<br />';
    $subject->notifyObservers();
 
    /* 添加第二个观察者 */
    $observer2 = new ConcreteObserver('phppan');
    $subject->attach($observer2);
 
    echo '<br /> The Second notify:<br />';
    $subject->notifyObservers();
 
    /* 删除第一个观察者 */
    $subject->detach($observer1);
 
    echo '<br /> The Third notify:<br />';
    $subject->notifyObservers();
  }
 
}
 
Client::main();
?>

以上就是使用php实现观察者模式的代码,还有一些关于观察者模式的概念区分,希望对大家的学习有所帮助。

PHP 相关文章推荐
使用 php4 加速 web 传输
Oct 09 PHP
php用header函数实现301跳转代码实例
Nov 25 PHP
Symfony学习十分钟入门经典教程
Feb 03 PHP
PHP使用PDO操作数据库的乱码问题解决方法
Apr 08 PHP
浅谈PHP Cookie处理函数
Jun 10 PHP
php并发加锁示例
Oct 17 PHP
PHP常用的三种设计模式
Feb 17 PHP
PHP开发APP端微信支付功能
Feb 17 PHP
PHP7.1实现的AES与RSA加密操作示例
Jun 15 PHP
基于ThinkPHP5框架使用QueryList爬取并存入mysql数据库操作示例
May 25 PHP
php面试实现反射注入的详细方法
Sep 30 PHP
基于PHP实现解密或加密Cloudflar邮箱保护
Jun 24 PHP
PHP判断手机是IOS还是Android
Dec 09 #PHP
PHP的Yii框架的常用日志操作总结
Dec 08 #PHP
Linux系统下使用XHProf和XHGui分析PHP运行性能
Dec 08 #PHP
thinkPHP中create方法与令牌验证实例浅析
Dec 08 #PHP
详解PHP的Yii框架中日志的相关配置及使用
Dec 08 #PHP
UPUPW 更新 64 位 Apache 系列 PHP 7.0 正式版
Dec 08 #PHP
学习php设计模式 php实现模板方法模式
Dec 08 #PHP
You might like
《DOTA3》开发工作已经开始 《DOTA3》将代替《DOTA2》
2021/03/06 DOTA
PHP的FTP学习(二)
2006/10/09 PHP
php防止sql注入示例分析和几种常见攻击正则表达式
2014/01/12 PHP
图文详解PHP环境搭建教程
2016/07/16 PHP
用php和jQuery来实现“顶”和“踩”的投票功能
2016/10/13 PHP
php和nginx交互实例讲解
2019/09/24 PHP
28个JS验证函数收集
2010/03/02 Javascript
基于jquery的无刷新分页技术
2011/06/11 Javascript
jquery实现图片等比例缩放以及max-width在ie中不兼容解决
2013/03/21 Javascript
jQuery trigger()方法用法介绍
2015/01/13 Javascript
jQuery网页右侧广告跟随滚动代码分享
2020/04/20 Javascript
BootStrap树状图显示功能
2016/11/24 Javascript
JavaScript中的toString()和toLocaleString()方法的区别
2017/02/15 Javascript
JS检测是否可以访问公网服务器功能代码
2017/06/19 Javascript
浅谈react+es6+webpack的基础配置
2017/08/09 Javascript
浅谈Webpack 持久化缓存实践
2018/03/22 Javascript
vue使用微信扫一扫功能的实现代码
2020/04/11 Javascript
[51:17]Mineski vs Secret 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.22
2019/09/05 DOTA
详解使用pymysql在python中对mysql的增删改查操作(综合)
2017/01/18 Python
itchat接口使用示例
2017/10/23 Python
python中lambda()的用法
2017/11/16 Python
Python实现的生成格雷码功能示例
2018/01/24 Python
Python3中内置类型bytes和str用法及byte和string之间各种编码转换 问题
2018/09/27 Python
Python运维开发之psutil库的使用详解
2018/10/18 Python
Python实现截取PDF文件中的几页代码实例
2019/03/11 Python
详解mac python+selenium+Chrome 简单案例
2019/11/08 Python
快速解决jupyter启动卡死的问题
2020/04/10 Python
在网络中有两台主机A和B,并通过路由器和其他交换设备连接起来,已经确认物理连接正确无误,怎么来测试这两台机器是否连通?如果不通,怎么来判断故障点?怎么排
2014/01/13 面试题
年终总结会主持词
2014/03/25 职场文书
集体生日活动方案
2014/08/18 职场文书
模范教师材料大全
2014/12/16 职场文书
幼儿教师2014年度工作总结
2014/12/16 职场文书
优秀党员事迹材料
2014/12/18 职场文书
Java Kafka 消费积压监控的示例代码
2021/07/01 Java/Android
Vue图片裁剪组件实例代码
2021/07/02 Vue.js
Java实现注册登录跳转
2022/06/16 Java/Android