学习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 相关文章推荐
php下MYSQL limit的优化
Jan 10 PHP
php 生成随机验证码图片代码
Feb 08 PHP
用php来改写404错误页让你的页面更友好
Jan 24 PHP
如何使用PHP计算上一个月的今天
May 23 PHP
最常用的8款PHP调试工具
Jul 06 PHP
Yii中的relations数据关联查询及统计功能用法详解
Jul 14 PHP
php 实现301重定向跳转实例代码
Jul 18 PHP
功能强大的php分页函数
Jul 20 PHP
PHP中explode函数和split函数的区别小结
Aug 24 PHP
php事件驱动化设计详解
Nov 10 PHP
浅谈PHP的反射机制
Dec 15 PHP
修改Laravel自带的认证系统的User类的命名空间的步骤
Oct 15 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
从php核心代码分析require和include的区别
2011/01/02 PHP
PHPThumb图片处理实例
2014/05/03 PHP
php如何计算两坐标点之间的距离
2018/12/29 PHP
PHP封装的分页类与简单用法示例
2019/02/25 PHP
轻轻松松学习JavaScript
2007/02/25 Javascript
不同的jQuery API来处理不同的浏览器事件
2012/12/09 Javascript
web的各种前端打印方法之jquery打印插件PrintArea实现网页打印
2013/01/09 Javascript
JavaScript中for循环的使用详解
2015/06/03 Javascript
从0开始学Vue
2016/10/27 Javascript
Bootstrap栅格系统的使用和理解2
2016/12/14 Javascript
ajax图片上传,图片异步上传,更新实例
2016/12/30 Javascript
使用 electron 实现类似新版 QQ 的登录界面效果(阴影、背景动画、窗体3D翻转)
2018/10/23 Javascript
Angular脚手架开发的实现步骤
2019/04/09 Javascript
JS实现网站吸顶条
2020/01/08 Javascript
基于javascript处理nginx请求过程详解
2020/07/07 Javascript
js代码编写无缝轮播图
2020/09/13 Javascript
[03:58]2014DOTA2国际邀请赛 龙宝赛后解密DK获胜之道
2014/07/14 DOTA
让python同时兼容python2和python3的8个技巧分享
2014/07/11 Python
Python类定义和类继承详解
2015/05/08 Python
Python对切片命名的实现方法
2018/10/16 Python
python3.6下Numpy库下载与安装图文教程
2019/04/02 Python
python pandas获取csv指定行 列的操作方法
2019/07/12 Python
Python 使用元类type创建类对象常见应用详解
2019/10/17 Python
新建文件时Pycharm中自动设置头部模板信息的方法
2020/04/17 Python
keras 两种训练模型方式详解fit和fit_generator(节省内存)
2020/07/03 Python
利用Storage Event实现页面间通信的示例代码
2018/07/26 HTML / CSS
三星新西兰官网:Samsung新西兰
2019/03/05 全球购物
面向对象编程OOP的优点
2013/01/22 面试题
基于Python 函数和方法的区别说明
2021/03/24 Python
读群众路线心得体会
2014/03/07 职场文书
中班开学寄语
2014/04/04 职场文书
开展党的群众路线教育实践活动情况汇报
2014/11/05 职场文书
解除劳动合同证明书模板
2014/11/20 职场文书
优秀党员主要事迹范文
2015/11/05 职场文书
如何用python识别滑块验证码中的缺口
2021/04/01 Python
代码解析React中setState同步和异步问题
2021/06/03 Javascript