GoF著作中未提到的设计模式(2):Interceptor
转:http://www.cnblogs.com/west-link/archive/2011/06/22/2086591.html
拦截器模式为我们提供了一种拦截方法调用或消息的途径,整个过程是自动的、透明的,下面是一个简单的拦截器示意图:

从图中可以看到,拦截器可以访问到方法调用的输入参数和返回结果,这样的话,拦截器能做的事儿就多啦,比如: 1、验证输入参数是否正确 2、偷偷地修改参数的值,例如参数类型的自动转换等 3、依赖注入 4、修改返回结果的内容、格式等
下面是一个包含我们要拦截的方法的类:
public class Action{
// 拦截器集合的迭代器
private Iterator interceptors;
// 输入参数
private Parameter param;
// 返回结果
private Result result;
// 构造函数
public Action(Parameter param);
// 这个方法是我们要拦截的(具体实现见下面)
public Result invoke();
// 其他...
}
下面声明一个拦截器接口:
public interface Interceptor{
public Result intercept(Action action);
}
我们可能会想到以下的拦截方式:
// 先在方法调用之前拦截一下,可以处理输入参数
intercept(param);
// 调用方法
result = action.invoke(param);
// 在方法调用之后再拦截一下,可以处理返回结果
intercept(result);
这种方式的缺点是不能完全地控制方法的调用,比如不能跳过方法的调用而直接返回结果、不能更改所在对象内部的状态等。
下面的实现也能达到方法调用的前后拦截,并且有完全控制该对象的能力
public Result invoke(){
if( interceptors.hasNext() ){
Interceptor interceptor = interceptors.next();
result = interceptor.intercept(this);
}
}
下面我们举几个拦截的具体例子:
// 参数合法性验证拦截器
public ParamInvalidator implements Interceptor{
public Result intercept(Action action){
Paramemter param = action.getParam();
// 确保参数不为null
if(param == null){
addMessege("param is null!");
// 创建一个默认的参数对象
action.setParam(new Paramemter());
}
// 继续调用过程
return action.invoke();
}
}
一般来说,这类拦截器应该放在拦截器集合的最前面,所以,拦截器的被执行顺序是比较重要的!这依赖于具体的实现需求。
如果需求有要求:参数为null时直接返回一个null的结果,停止调用过程,那么我们可以把上面的方法改成这样:
public Result intercept(Action action){
Paramemter param = action.getParam();
if(param == null){
return null;
}
// 继续调用过程
return action.invoke();
}
所以,在所有的拦截器的实现中,action.invoke()这一行代码的位置或者有无非常重要,通过控制它我们就能在调用的前后进行拦截,甚至不调用它!
public interface MoneyAware{
public void setMoney(int money);
}
// 依赖注入拦截器
public DependencyInjector implements Interceptor{
public Result intercept(Action action){
// 如果它实现了MoneyAware接口,那么我们就给它注入5毛钱
if(action instanceof MoneyAware){
action.setMoney(5);
}
// 继续调用过程
return action.invoke();
}
}
从这个拦截器可以看出,我们能修改被拦截对象的内部状态。
// 结果格式化拦截器
public ResultFormater implements Interceptor{
public Result intercept(Action action){
// 先调用要拦截的方法
result = action.invoke();
// 将结果格式化
formatResult(result);
// 返回结果
return result;
}
}
这个拦截器就是方法调用后的拦截,所以这种拦截器被执行的时候被放在调用堆栈的最下面,当其他拦截器执行完后,它才被执行!
GoF著作中未提到的设计模式(2):Interceptor的更多相关文章
- GOF---Java开发中的23种设计模式详解
表点 设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式 ...
- Java开发中的23种设计模式详解(转)
设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- Java开发中的23种设计模式(转)
设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- 0. Java开发中的23种设计模式详解(转)
设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- JDK中所包含的设计模式
本文主要是归纳了JDK中所包含的设计模式,包括作用和其设计类图.首先来个总结,具体的某个模式可以一个一个慢慢写,希望能对研究JDK和设计模式有所帮助. 一.设计模式是什么(1)反复出现问题的解决方案( ...
- Java开发中的23种设计模式(转)
设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- Java开发中的23种设计模式
设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- [转载]java开发中的23种设计模式
原文链接:http://blog.csdn.net/zhangerqing 设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反 ...
- 【java】java开发中的23种设计模式详解
设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
随机推荐
- vue-cli构建的项目中请求代理与项目打包
vue-cli构建的项目中,生产模式下的打包路径.与生产模式下的请求代理简单示意
- spring约束
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- 小程序解析HTML5
最近做项目的时候碰到一个问题,就是调用接口获取信息到页面上,内容与HTML5标签一起获取过来了.一起显示在微信端上.一般都是二次开发才有可能出现这种问题.通过查找方法,找到了一个可以把HTML5标签转 ...
- 24. Jmeter GUI 及NON GUI实现分布式
什么是分布式: Jmeter的集群模式可以让我们将多台机器联合起来一起产生负载,从而弥补单台机器负载生成能力不足的问题. 假设我们的测试计划会产生100个threads,我们使用6台机器进行分布式测试 ...
- 入门 Webpack,看这篇就够
写在前面的话 阅读本文之前,先看下面这个webpack的配置文件,如果每一项你都懂,那本文能带给你的收获也许就比较有限,你可以快速浏览或直接跳过:如果你和十天前的我一样,对很多选项存在着疑惑,那花一段 ...
- jmeter 查看结果树之查看响应的13种方法
查看结果树查看响应有哪几种方法,可通过左侧面板底部的下拉框选择 1 Text 查看结果树中请求的默认格式为Text,显示取样器结果.请求.响应数据3个部分内容. 取样器结果: 默认Raw展示,可以切换 ...
- 从零开始搭建系统1.2——Nginx安装及配置
一.安装准备 首先由于nginx的一些模块依赖一些lib库,所以在安装nginx之前,必须先安装这些lib库,这些依赖库主要有g++.gcc.openssl-devel.pcre-devel和zlib ...
- 压缩与解压缩 gzip bzip2 tar 命令
gzip压缩与解压缩 命令 gzip -v 解压缩 gzip-d 操作如下. 压缩 .可以看到源文件有5171大小,压缩后,变成了1998大小. 解压缩 .解压缩之后可以看到,原来的man_db ...
- Replication Controller、Replica Set
假如我们现在有一个Pod正在提供线上的服务,我们来想想一下我们可能会遇到的一些场景: 某次运营活动非常成功,网站访问量突然暴增 运行当前Pod的节点发生故障了,Pod不能正常提供服务了 第一种情况,可 ...
- zabbix active模式以及自定义key not Supported的解决
zabbix active模式 active模式适用场景 zabbix server端无法直连agent端,比如agent为内网机器,仅有内网ip,没有公网ip,但是内网机器能够访问server端 a ...