责任链的方法化

责任链的方法化

责任链模式是一个非常简单容易理解的模式。在书中的介绍中,责任链的使用时用类似链表的方式将对象建立起一条链。这样的方式怎么说呢?有好有坏吧。

===================

概念

责任链模式:将多个处理请求的对象按照优先级连成一条链,并沿着该条链处理请求,使得多个对象都有机会处理。

应用场景分析

我们先从书中(设计模式之禅)的最后例子开始分析。

案例:注册时有两类注册:VIP用户和普通用户(我们假设还有其他类型用户C和D),注册后不管是什么用户,直接用责任链模式传入进行处理。

这个案例,真的用最中规中矩的方式实现真的合适吗?

我觉得不,责任链类它不单一!!不符合迪米特!!

先看责任链类代码

public abstract class Handler {

    /**
     * 持有后继的责任对象
     */
    protected Handler successor;
    /**
     * 示意处理请求的方法,虽然这个示意方法是没有传入参数的
     * 但实际是可以传入参数的,根据具体需要来选择是否传递参数
     */
    public abstract void handleRequest();
    /**
     * 取值方法
     */
    public Handler getSuccessor() {
        return successor;
    }
    /**
     * 赋值方法,设置后继的责任对象
     */
    public void setSuccessor(Handler successor) {
        this.successor = successor;
    }

}

public class ConcreteHandler extends Handler {
    /**
     * 处理方法,调用此方法处理请求
     */
    @Override
    public void handleRequest() {
        /**
         * 判断是否有后继的责任对象
         * 如果有,就转发请求给后继的责任对象
         * 如果没有,则处理请求
         */
        if(getSuccessor() != null)
        {            
           System.out.println("放过请求");
           getSuccessor().handleRequest();            
        }else
        {            
            System.out.println("处理请求");
        }
    }
}

最浅显的不合理,责任链更适合有优先级关系的任务,而不是这样平级的任务。

我们再分析这四个模块。这些个处理方式都应该是互不相关完全独立的模块,这些模块我应该可以在任何一个地方去调用。

那么现在将这些本应该独立处理的模块塞进Handler里的的handleRequest()方法里,让这些模块不得不去判断传来的消息自己能不能处理,还要知道下一步要交给谁处理。

那么这样做的后果是什么呢?

  • 混入了其他职责,模块不再单一
  • 知道了一些本不需要知道的“只是”。
  • 使用场景被固化,当我只想处理普通用户时,必须通过责任链。
  • 当处理方法越来越多时,对链的维护成了问题。

然后你就会问啦~那我不可以这样吗?

  • 模块依然独立,只是在责任链中组合处理模块。

    这样的责任链,有种壳外加壳,为了责任链而责任链的感觉了,有更好的办法。

  • 我的使用场景本来就是固定的,这些处理模块真的只是在注册时才用。

    那如果我新做了一个兄弟产品,只有普通用户这一种,独立模块我可以直接搬过来,责任链反而需要改代码。

那么我认为的最佳实践应该是如何的呢?

责任链模式的核心是链~在优先级需求上的链式处理。

1.各处理模块应该独立封装。
2.平级的处理任务并不适合责任链,用if else反而更合适。如果if else 过多,可以提供一个单独的类进行分发处理。
public class Handler {

    /**
     * 持有后继的责任对象
     */
    protected Handler successor;
    /**
     * 示意处理请求的方法,虽然这个示意方法是没有传入参数的
     * 但实际是可以传入参数的,根据具体需要来选择是否传递参数
     */
    public void handleRequest(Response response){
        switch(response.getId()){
            case 1:
            new VipHandle(response);
            break;

            case 2:
            new DefaultHandle(response);
            break;
        }
    }
}
3.在有优先级情况下,处理代码并不多的情况下,更建议使用方法化的责任链模式。在维持到一定数量级以下,类的维护成本是高于方法的。
/**
 * 检查banner状态并返回要显示内容
 */
private String bannerChainState(){
    return bannerChainNet();
}

/**
 * 检查网络状态并返回要显示内容
 */
private String bannerChainNet(){
    if(NetWork.isClose())
        return "请打开网络";
    else
        return bannerChainGps();
}

/**
 * 检查Gps状态并返回要显示内容
 */
private String bannerChainGps(){
    if(Gps.isClose())
        return "请开启GPs";
    else
        return bannerChainLogin();
}

/**
 * 检查登录状态并返回要显示内容
 */
private String bannerChainLogin(){
    if(Login.isLogin())
        reutrn "请登录";
    else
        return bannerChainData();
}

/**
 * 检查通知信息并返回要显示内容
 */
private String bannerChainData(){
    return "你有一条新通知";
}

责任链的适用处与优点

  • 有明显优先级关系的处理任务适合责任链

  • 对链式处理的过程有需求的适合责任链。(如对每个处理任务后的计数需求)

责任链缺点

  • 抛开链式结构,请求与处理的解耦实现有比责任链更好的方法。(如提供一个事件分发类、工厂+策略模式等等)

  • 责任链某种程度违反了单一和迪米特

  • 链很长的情况下,效率是很严重的问题。

  • 额外增加了链的维护成本。(想象一下链表的删除节点与插入节点)

  • 使用方法化的责任链思想,在维护和代码阅读上有更多优点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值