热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PHP设计模式之责任链模式的深入解析

本篇文章是对PHP设计模式中的责任链模式进行了详细的分析介绍,需要的朋友参考下
责任链模式,其目的是组织一个对象链处理一个如方法调用的请求。
当ConcreteHandler(具体的处理程序)不知道如何满足来自Client的请求时,或它的目的不是这个时,它会委派给链中的下一个Handler(处理程序)来处理。

这个设计模式通常和复合模式一起使用,其中有些叶子或容器对象默认委派操作给它们的父对象。另一个例子是,本地化通常是使用责任链处理的,当德语翻译适配器没有为翻译关键词找到合适的结果时,就返回到英语适配器或干脆直接显示关键词本身。

耦合减少到最低限度:Client类不知道由哪个具体的类来处理请求;在创建对象图时配置了链;ConcreteHandlers不知道哪个对象是它们的继承者。行为在对象之间分配是成功的,链中最近的对象有优先权和责任满足请求。

参与者:
◆Client(客户端):向Handler(处理程序)提交一个请求;
◆Handler(处理程序)抽象:接收一个请求,以某种方式满足它;
◆ConcreteHandlers(具体的处理程序):接收一个请求,设法满足它,如果不成功就委派给下一个处理程序。
下面的代码实现了一个最著名的责任链示例:多级缓存。

代码如下:


/**
* The Handler abstraction. Objects that want to be a part of the
* ChainOfResponsibility must implement this interface directly or via
* inheritance from an AbstractHandler.
*/
interface KeyValueStore
{
/**
* Obtain a value.
* @param string $key
* @return mixed
*/
public function get($key);
}

/**
* Basic no-op implementation which ConcreteHandlers not interested in
* caching or in interfering with the retrieval inherit from.
*/
abstract class AbstractKeyValueStore implements KeyValueStore
{
protected $_nextHandler;

public function get($key)
{
return $this->_nextHandler->get($key);
}
}

/**
* Ideally the last ConcreteHandler in the chain. At least, if inserted in
* a Chain it will be the last node to be called.
*/
class SlowStore implements KeyValueStore
{
/**
* This could be a somewhat slow store: a database or a flat file.
*/
protected $_values;

public function __construct(array $values = array())
{
$this->_values = $values;
}

public function get($key)
{
return $this->_values[$key];
}
}

/**
* A ConcreteHandler that handles the request for a key by looking for it in
* its own cache. Forwards to the next handler in case of cache miss.
*/
class InMemoryKeyValueStore implements KeyValueStore
{
protected $_nextHandler;
protected $_cached = array();

public function __construct(KeyValueStore $nextHandler)
{
$this->_nextHandler = $nextHandler;
}

protected function _load($key)
{
if (!isset($this->_cached[$key])) {
$this->_cached[$key] = $this->_nextHandler->get($key);
}
}

public function get($key)
{
$this->_load($key);
return $this->_cached[$key];
}
}

/**
* A ConcreteHandler that delegates the request without trying to
* understand it at all. It may be easier to use in the user interface
* because it can specialize itself by defining methods that generates
* html, or by addressing similar user interface concerns.
* Some Clients see this object only as an instance of KeyValueStore
* and do not care how it satisfy their requests, while other ones
* may use it in its entirety (similar to a class-based adapter).
* No client knows that a chain of Handlers exists.
*/
class FrontEnd extends AbstractKeyValueStore
{
public function __construct(KeyValueStore $nextHandler)
{
$this->_nextHandler = $nextHandler;
}

public function getEscaped($key)
{
return htmlentities($this->get($key), ENT_NOQUOTES, 'UTF-8');
}
}

// Client code
$store = new SlowStore(array('pd' => 'Philip K. Dick',
'ia' => 'Isaac Asimov',
'ac' => 'Arthur C. Clarke',
'hh' => 'Helmut Heißenbüttel'));
// in development, we skip cache and pass $store directly to FrontEnd
$cache = new InMemoryKeyValueStore($store);
$frOntEnd= new FrontEnd($cache);

echo $frontEnd->get('ia'), "\n";
echo $frontEnd->getEscaped('hh'), "\n";


关于PHP责任链设计模式的一些实现说明:
◆责任链可能已经存在于对象图中,和复合模式的例子一样;
◆此外,Handler抽象可能存在,也可能不存在,最好的选择是一个分开的Handler接口只可以执行handleRequest()操作,不要强制一个链只在一个层次中,因为后面的已经存在了;
◆也可能引入一个抽象类,但由于请求处理是一个正交关注,因此具体的类可能已经继承了其它类;
◆通过constructor 或setter,Handler(或下一个Handler)被注入到Client或前一个Handler;
◆请求对象通常是一个ValueObject,也可能被实现为一个Flyweight,在PHP中,它可能是一个标量类型,如string,注意在某些语言中,一个string就是一个不变的ValueObject。

简单的总结责任链模式,可以归纳为:用一系列类(classes)试图处理一个请求request,这些类之间是一个松散的耦合,唯一共同点是在他们之间传递request. 也就是说,来了一个请求,A类先处理,如果没有处理,就传递到B类处理,如果没有处理,就传递到C类处理,就这样象一个链条(chain)一样传递下去。
推荐阅读
  • 延迟注入工具(python)的SQL脚本
    本文介绍了一个延迟注入工具(python)的SQL脚本,包括使用urllib2、time、socket、threading、requests等模块实现延迟注入的方法。该工具可以通过构造特定的URL来进行注入测试,并通过延迟时间来判断注入是否成功。 ... [详细]
  • 本文介绍了Java的集合及其实现类,包括数据结构、抽象类和具体实现类的关系,详细介绍了List接口及其实现类ArrayList的基本操作和特点。文章通过提供相关参考文档和链接,帮助读者更好地理解和使用Java的集合类。 ... [详细]
  • 本文介绍了一个免费的asp.net控件,该控件具备数据显示、录入、更新、删除等功能。它比datagrid更易用、更实用,同时具备多种功能,例如属性设置、数据排序、字段类型格式化显示、密码字段支持、图像字段上传和生成缩略图等。此外,它还提供了数据验证、日期选择器、数字选择器等功能,以及防止注入攻击、非本页提交和自动分页技术等安全性和性能优化功能。最后,该控件还支持字段值合计和数据导出功能。总之,该控件功能强大且免费,适用于asp.net开发。 ... [详细]
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了绕过WAF的XSS检测机制的方法,包括确定payload结构、测试和混淆。同时提出了一种构建XSS payload的方法,该payload与安全机制使用的正则表达式不匹配。通过清理用户输入、转义输出、使用文档对象模型(DOM)接收器和源、实施适当的跨域资源共享(CORS)策略和其他安全策略,可以有效阻止XSS漏洞。但是,WAF或自定义过滤器仍然被广泛使用来增加安全性。本文的方法可以绕过这种安全机制,构建与正则表达式不匹配的XSS payload。 ... [详细]
  • 本文讨论了微软的STL容器类是否线程安全。根据MSDN的回答,STL容器类包括vector、deque、list、queue、stack、priority_queue、valarray、map、hash_map、multimap、hash_multimap、set、hash_set、multiset、hash_multiset、basic_string和bitset。对于单个对象来说,多个线程同时读取是安全的。但如果一个线程正在写入一个对象,那么所有的读写操作都需要进行同步。 ... [详细]
  • 背景应用安全领域,各类攻击长久以来都危害着互联网上的应用,在web应用安全风险中,各类注入、跨站等攻击仍然占据着较前的位置。WAF(Web应用防火墙)正是为防御和阻断这类攻击而存在 ... [详细]
author-avatar
七锦少年
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有