<?php
class Paper{
private $_observers = array();
public function register($sub){
$this->_observers[] = $sub;
} public function trigger(){
if(!empty($this->_observers)){
foreach($this->_observers as $observer){
$observer->update();
}
}
}
} interface Observerable{
public function update();
} class Subscriber implements Observerable{
public $name = "";
public function __construct($name){
$this->name = $name;
}
public function update(){
echo $this->name." callback\n";
}
} $paper = new Paper();
$paper->register(new Subscriber('xiaoming'));
$paper->register(new Subscriber('xiaoli'));
$paper->trigger();

  被观察者通过自身的接口,将观察者注册到自己的属性里。

当触发调用的时候通过观察者统一实现的接口方法通知观察者。

当有新的观察者进来的时候,只需要新观察者实现接口,然后注册到被观察者属性里就可以啦。

这降低了主题对象和观察者对象的耦合度。

设计原则

在观察者模式中,会改变的是主题的状态以及观察者的数目。用这个模式,你可以改变依赖于主题状态的对象,却不必改变主题。——找出程序中会变化的方面,然后将其和固定不变的方面相分离!
 
 主题和观察者都使用接口:观察者利用主题的接口向主题注册,而主题利用观察者接口通知观察者。这样可以让两者之间运作正常,又同时具有松耦合的优点! ——针对接口编程,不针对实现编程!
 观察者模式利用“组合”将许多观察者组合进主题中。对象(观察者——主题)之间的这种关系不是通过继承产生的,而是在运行时利用组合的方式产生的。 ——多用组合,少用继承!

http://www.cnblogs.com/baochuan/archive/2012/02/22/2362668.html

Thinkphp3.2.3就是通过这个模式来实现的。

\Tinkphp\Core\Library\Think\Think.class.php

81-83行,通过这个注册,观察者;

          // 加载应用行为定义
if(is_file(CONF_PATH.'tags.php'))
// 允许应用增加开发模式配置定义
Hook::import(include CONF_PATH.'tags.php');

  附上被观察者源码;

\Thinkphp\Core\Library\Think\Hook.class.php

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2013 http://topthink.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace Think;
/**
* ThinkPHP系统钩子实现
*/
class Hook { static private $tags = array(); /**
* 动态添加插件到某个标签
* @param string $tag 标签名称
* @param mixed $name 插件名称
* @return void
*/
static public function add($tag,$name) {
if(!isset(self::$tags[$tag])){
self::$tags[$tag] = array();
}
if(is_array($name)){
self::$tags[$tag] = array_merge(self::$tags[$tag],$name);
}else{
self::$tags[$tag][] = $name;
}
} /**
* 批量导入插件
* @param array $data 插件信息
* @param boolean $recursive 是否递归合并
* @return void
*/
static public function import($data,$recursive=true) {
if(!$recursive){ // 覆盖导入
self::$tags = array_merge(self::$tags,$data);
}else{ // 合并导入
foreach ($data as $tag=>$val){
if(!isset(self::$tags[$tag]))
self::$tags[$tag] = array();
if(!empty($val['_overlay'])){
// 可以针对某个标签指定覆盖模式
unset($val['_overlay']);
self::$tags[$tag] = $val;
}else{
// 合并模式
self::$tags[$tag] = array_merge(self::$tags[$tag],$val);
}
}
}
} /**
* 获取插件信息
* @param string $tag 插件位置 留空获取全部
* @return array
*/
static public function get($tag='') {
if(empty($tag)){
// 获取全部的插件信息
return self::$tags;
}else{
return self::$tags[$tag];
}
} /**
* 监听标签的插件
* @param string $tag 标签名称
* @param mixed $params 传入参数
* @return void
*/
static public function listen($tag, &$params=NULL) {
if(isset(self::$tags[$tag])) {
if(APP_DEBUG) {
G($tag.'Start');
trace('[ '.$tag.' ] --START--','','INFO');
}
foreach (self::$tags[$tag] as $name) {
APP_DEBUG && G($name.'_start');
$result = self::exec($name, $tag,$params);
if(APP_DEBUG){
G($name.'_end');
trace('Run '.$name.' [ RunTime:'.G($name.'_start',$name.'_end',6).'s ]','','INFO');
}
if(false === $result) {
// 如果返回false 则中断插件执行
return ;
}
}
if(APP_DEBUG) { // 记录行为的执行日志
trace('[ '.$tag.' ] --END-- [ RunTime:'.G($tag.'Start',$tag.'End',6).'s ]','','INFO');
}
}
return;
} /**
* 执行某个插件
* @param string $name 插件名称
* @param string $tag 方法名(标签名)
* @param Mixed $params 传入的参数
* @return void
*/
static public function exec($name, $tag,&$params=NULL) {
if('Behavior' == substr($name,-8) ){
// 行为扩展必须用run入口方法
$tag = 'run';
}
$addon = new $name();
return $addon->$tag($params);
}
}

  

php观察折模式的更多相关文章

  1. Unity 消息管理(观察煮模式)

    一.首先定义一份消息号(消息号用来标记发出的每一条消息,接收者通过注册要监听的消息号来监听相应的消息) public enum MSG_IDS { NONE = -, MSG_TEST01 = , M ...

  2. java 观察这模式(发布订阅模式)

    观察者设计模式定义了对象间的一种一对多的组合关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新. 发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息. 抽象 ...

  3. 观察者(Observer)模式

    http://www.cnblogs.com/zhenyulu/articles/73723.html 一. 观察者(Observer)模式 观察者模式又叫做发布-订阅(Publish/Subscri ...

  4. 《大话》之 策略模式 Vs 状态模式

    一.简介: 策略模式: 背景:商店要打折销售,各种版本的销售方式,让小菜心烦意乱 内容:    定义算法家族,分别封装起来,让他们之间可以户型替换,此模式让算法的变化,不会影响到使用算法的用户. 图文 ...

  5. Java Observable 模式

    一.Observer模式的意图: 在对象的内部状态发生变化时,自动通知外部对象进行响应. 二.Observer模式的构成: ·被观察者:内部状态有可能被改变,而且又需要通知外部的对象 ·观察者:需要对 ...

  6. 《java与模式》

    2012年3月 随笔档案 - java_my_life - 博客园--此网友 12年的博客都是和模式有关的,希望可以多看看.http://www.cnblogs.com/java-my-life/ar ...

  7. 搞懂:MVVM模型以及VUE中的数据绑定数据劫持发布订阅模式

    搞懂:MVVM模式和Vue中的MVVM模式 MVVM MVVM : model - view - viewmodel的缩写,说都能直接说出来 model:模型,view:视图,view-Model:视 ...

  8. JVM原理和优化

    JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.exe来完成,通过下面4步来完成JVM环境. 1.创建JVM装载环境和配置 2.装载JVM.dll 3.初始化JVM.dll并挂界 ...

  9. jvm 原理和优化

    在csdn 上看到的,觉得很好,收藏了: 原博文地址: 濤子 http://blog.csdn.net/ning109314/article/details/10411495/ JVM工作原理和特点主 ...

随机推荐

  1. hdu 4549 M斐波那契数列(矩阵高速幂,高速幂降幂)

    http://acm.hdu.edu.cn/showproblem.php?pid=4549 f[0] = a^1*b^0%p,f[1] = a^0*b^1%p,f[2] = a^1*b^1%p... ...

  2. java学习总结——你的前世今生

    一.背景 JAVA语言最開始仅仅是Sun电脑(Sun MicroSystems)公司在1990年12月開始研究的一个内部项目. Sun电脑公司的一个叫做帕特里克·诺顿的project师被公司自己开发的 ...

  3. jquery 实现可编辑div

    html大致例如以下: <ol id="ol_group" class="list-group list_of_items"> <li cla ...

  4. Cadence——每次启动软件弹出找不到license文件的提示窗口

    1. 摘要 按照Cadence16.60,每次启动该软件,总弹出提示窗口,内如大致为:Orcad Capture license was not found.... 2. 解决方法 参考此链接:htt ...

  5. timeout in asp.net

    Forms authentication timeout vs sessionState timeout They are different things. The Forms Authentica ...

  6. How to: Specify the Web Server for Web Projects in Visual Studio

    https://msdn.microsoft.com/en-us/library/ms178108(v=vs.120).aspx When you run a Web project in Visua ...

  7. anaconda安装python三方包,以tensorflow为例

    Anaconda概述 Anaconda是一个用于科学计算的Python发行版,支持 Linux, Mac, Windows系统,提供了包管理与环境管理的功能,可以很方便地解决多版本python并存.切 ...

  8. residual sum of squares(ESL 读书笔记)

    The learning algorithm has the property that it can modify its input/output relationship f-hat in re ...

  9. bzoj3545

    线段树合并+离线+启发式合并 半年前这道题t成狗... 离线的做法比较好想,按照边的权值排序,询问的权值排序,然后枚举询问不断加边,加到上限后查找第k大值,这里平衡树,权值线段树都可以实现. 那么我们 ...

  10. JAVA基础(多线程Thread和Runnable的使用区别(转载)

    转自:http://jinguo.iteye.com/blog/286772 Runnable是Thread的接口,在大多数情况下“推荐用接口的方式”生成线程,因为接口可以实现多继承,况且Runnab ...