责任链的方法化
责任链模式是一个非常简单容易理解的模式。在书中的介绍中,责任链的使用时用类似链表的方式将对象建立起一条链。这样的方式怎么说呢?有好有坏吧。
===================
概念
责任链模式:将多个处理请求的对象按照优先级连成一条链,并沿着该条链处理请求,使得多个对象都有机会处理。
应用场景分析
我们先从书中(设计模式之禅)的最后例子开始分析。
案例:注册时有两类注册: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 "你有一条新通知";
}
责任链的适用处与优点
有明显优先级关系的处理任务适合责任链
对链式处理的过程有需求的适合责任链。(如对每个处理任务后的计数需求)
责任链缺点
抛开链式结构,请求与处理的解耦实现有比责任链更好的方法。(如提供一个事件分发类、工厂+策略模式等等)
责任链某种程度违反了单一和迪米特
链很长的情况下,效率是很严重的问题。
额外增加了链的维护成本。(想象一下链表的删除节点与插入节点)
使用方法化的责任链思想,在维护和代码阅读上有更多优点。