php观察折模式
<?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观察折模式的更多相关文章
- Unity 消息管理(观察煮模式)
一.首先定义一份消息号(消息号用来标记发出的每一条消息,接收者通过注册要监听的消息号来监听相应的消息) public enum MSG_IDS { NONE = -, MSG_TEST01 = , M ...
- java 观察这模式(发布订阅模式)
观察者设计模式定义了对象间的一种一对多的组合关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新. 发布者发布信息,订阅者获取信息,订阅了就能收到信息,没订阅就收不到信息. 抽象 ...
- 观察者(Observer)模式
http://www.cnblogs.com/zhenyulu/articles/73723.html 一. 观察者(Observer)模式 观察者模式又叫做发布-订阅(Publish/Subscri ...
- 《大话》之 策略模式 Vs 状态模式
一.简介: 策略模式: 背景:商店要打折销售,各种版本的销售方式,让小菜心烦意乱 内容: 定义算法家族,分别封装起来,让他们之间可以户型替换,此模式让算法的变化,不会影响到使用算法的用户. 图文 ...
- Java Observable 模式
一.Observer模式的意图: 在对象的内部状态发生变化时,自动通知外部对象进行响应. 二.Observer模式的构成: ·被观察者:内部状态有可能被改变,而且又需要通知外部的对象 ·观察者:需要对 ...
- 《java与模式》
2012年3月 随笔档案 - java_my_life - 博客园--此网友 12年的博客都是和模式有关的,希望可以多看看.http://www.cnblogs.com/java-my-life/ar ...
- 搞懂:MVVM模型以及VUE中的数据绑定数据劫持发布订阅模式
搞懂:MVVM模式和Vue中的MVVM模式 MVVM MVVM : model - view - viewmodel的缩写,说都能直接说出来 model:模型,view:视图,view-Model:视 ...
- JVM原理和优化
JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.exe来完成,通过下面4步来完成JVM环境. 1.创建JVM装载环境和配置 2.装载JVM.dll 3.初始化JVM.dll并挂界 ...
- jvm 原理和优化
在csdn 上看到的,觉得很好,收藏了: 原博文地址: 濤子 http://blog.csdn.net/ning109314/article/details/10411495/ JVM工作原理和特点主 ...
随机推荐
- CVPR2015一些文章整理
简单看了一部分CVPR2015的文章.整理了一下. 当中我决定把精彩的文章加粗. 主要是认为有些文章仅仅读了一遍,没有发现非常多非常有道理的point(虽然我承认他们的工作都花了非常大的功夫.可是没有 ...
- bootstrap table 显示连续序号,分页有效
参考:http://blog.csdn.net/nazhidao/article/details/51647799 第一种,通过index+1可以简单实现,但是,翻页后又重新从第一个开始 { fiel ...
- linux内核中的宏ffs(x)
linux内核中ffs(x)宏是平台相关的宏,在arm平台,该宏定义在 arch/arm/include/asm/bitops.h #define ffs(x) ({ unsigned long __ ...
- iOS界面之间的跳转方式
iOS界面之间的跳转方式基本有3种. .改变window的根视图 [self.window setRootViewController:VC]; .模态弹出 [self presentViewCont ...
- IDEA Spark Streaming Kafka数据源-Producer
import java.util import org.apache.kafka.clients.producer.{KafkaProducer, ProducerConfig, ProducerRe ...
- [App Store Connect帮助]二、 添加、编辑和删除用户(3)添加和编辑用户
您可以在“用户和访问”中添加和编辑用户. 如果您以个人名义在“Apple 开发者计划”注册,您可以授权用户访问您 App Store Connect 中的内容.所有用户只拥有 App Store Co ...
- BZOJ 2178 Simpson积分
思路: 我发现能用Simpson积分水的题 好像都是裸题诶233333 //By SiriusRen #include <bits/stdc++.h> using namespace s ...
- shell script练习:利用日期进行文件的创建
随日期变化:利用 date 进行文件的创建 想像一个状况,假设我的服务器内有数据库,数据库每天的数据都不太一样,因此当我备份时, 希望将每天的数据都备份成不同的档名,这样才能够让旧的数据也能够保存下来 ...
- JVM 垃圾回收器详解
小结: 新生代 串行Serial 并行 Parallel(关注吞吐量) 并行ParNew 老年代 串行 Serial Old 并行Para ...
- 表格对象的获取和更改(原生js)
表格对象的获取 var oT = document.getElementById("tb"); //获取head console.log(oT.tHead); console.lo ...