首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件开发 >

GoF著述中未提到的设计模式(3):Interceptor (转载)

2012-07-22 
GoF著作中未提到的设计模式(3):Interceptor (转载)原文链接:http://www.cnblogs.com/west-link/archive/20

GoF著作中未提到的设计模式(3):Interceptor (转载)

原文链接:http://www.cnblogs.com/west-link/archive/2011/06/22/2086591.html

?

拦截器模式为我们提供了一种拦截方法调用或消息的途径,整个过程是自动的、透明的,下面是一个简单的拦截器示意图:

? GoF著述中未提到的设计模式(3):Interceptor (转载)

? 从图中可以看到,拦截器可以访问到方法调用的输入参数和返回结果,这样的话,拦截器能做的事儿就多啦,比如:
? 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;    }}

这个拦截器就是方法调用后的拦截,所以这种拦截器被执行的时候被放在调用堆栈的最下面,当其他拦截器执行完后,它才被执行!

?

特别说明:本人转载文章纯为技术学习,总结经验,并无其他目的,若有他人继续转载,请链接原作者的地址,而不是本文的地址,以示对作者的尊重。最后对原作者的辛勤劳动表示感谢!

热点排行