责任链模式(Iterator Pattern), 是行为型设计模式之一。这种模型结构有点类似现实生活中铁链,由一个个铁环首尾相接构成一条链,如果这种结构用在编程领域,则每个节点可以看做一个对象,每个对象有不同的处理逻辑,将一个请求从链的首端发出,沿着链的路径依次传递每个节点对象,直到有对象处理这个请求为止,我们将这样一种模式称为责任链模式。
1.多个对象可以处理同一个请求,但具体由哪个对象处理则在运行时动态决定。
2. 在请求处理者不明确的情况下向对个对象中的一个提交一个请求。
3. 需要动态处理一组对象处理请求。
下图是简单实现的责任链模式类UML图
角色介绍
AbsHandler:抽象处理者角色,声明一个请求处理的方法,并在其中保持一个对下一个处理节点Handler对象的引用。
ConcreteHandler:具体处理者角色,对请求进行处理,如果不能处理则将该请求转发给下一个节点上的处理对象。
public abstract class AbsHandler {
protected AbsHandler successor;
public abstract void handleRequest(String condition);
}
ConcreteHandler1
及ConcreteHandler2
public class ConcreteHandler1 extends AbsHandler {
@Override
public void handleRequest(String condition) {
if(condition.equals("ConcreteHandler1")){
return;
}else{
successor.handleRequest(condition);
}
}
}
public class ConcreteHandler2 extends AbsHandler {
@Override
public void handleRequest(String condition) {
if(condition.equals("ConcreteHandler2")){
return;
}else{
successor.handleRequest(condition);
}
}
}
public class Client {
public static void handlerRequest(){
AbsHandler handler1 = new ConcreteHandler1();
AbsHandler handler2 = new ConcreteHandler2();
handler1.successor = handler2;
handler2.successor = handler1;
handler1.handleRequest("ConcreteHandler2");
}
}
传入的"ConcreteHandler2"最终有Handler2完成处理。
简化版实现中我们的请求对象只是一个字符串,多数情况下,责任链中请求和对应处理规则是不尽相同的,在这种情况下可以将请求进行封装,同时对请求的处理规则也进行封装作为一个独立的对象。
下图是扩展后的责任链模式的类UML图
在AbstractHandler抽象处理者中,其声明了处理者对象处理请求的方法和获取处理级别的方法,并对具体处理转发逻辑进行实现。
AbstractHandler
public abstract class AbstractHandler {
protected static final String TAG = AbstractHandler.class.getSimpleName();
protected AbstractHandler nextHandler;
public final void handleRequest(AbstractRequest request){
if(getHandleLevel() == request.getRequestLevel()){
handle(request);
}else{
if(nextHandler!=null){
nextHandler.handle(request);
}else{
//当所有处理者对象均不能处理该请求时输出
Log.d(TAG,"All of handler can not handle the request");
}
}
}
protected abstract int getHandleLevel();
protected abstract void handle(AbstractRequest request);
}
AbstractRequest
类public abstract class AbstractRequest {
private Object object;
public AbstractRequest(Object object){
this.object = object;
}
public Object getContent(){
return object;
}
public abstract int getRequestLevel();
}
public class Handler1 extends AbstractHandler {
@Override
protected int getHandleLevel() {
return 1;
}
@Override
protected void handle(AbstractRequest request) {
Log.d(TAG, "Handler1 handler request:"+request.getRequestLevel());
}
}
public class Handler2 extends AbstractHandler {
@Override
protected int getHandleLevel() {
return 2;
}
@Override
protected void handle(AbstractRequest request) {
Log.d(TAG, "Handler2 handler request:"+request.getRequestLevel());
}
}
public class Handler3 extends AbstractHandler {
@Override
protected int getHandleLevel() {
return 3;
}
@Override
protected void handle(AbstractRequest request) {
Log.d(TAG, "Handler3 handler request:"+request.getRequestLevel());
}
}
public class Request1 extends AbstractRequest {
@Override
public int getRequestLevel() {
return 1;
}
public Request1(Object object) {
super(object);
}
@Override
public Object getContent() {
return super.getContent();
}
}
public class Request2 extends AbstractRequest {
@Override
public int getRequestLevel() {
return 2;
}
public Request2(Object object) {
super(object);
}
@Override
public Object getContent() {
return super.getContent();
}
}
public class Request3 extends AbstractRequest {
@Override
public int getRequestLevel() {
return 3;
}
public Request3(Object object) {
super(object);
}
@Override
public Object getContent() {
return super.getContent();
}
}
public class Client {
public static void handleRequest(){
AbstractHandler handler1 = new Handler1();
AbstractHandler handler2 = new Handler2();
AbstractHandler handler3 = new Handler3();
handler1.nextHandler = handler2;
handler2.nextHandler = handler3;
//构造三个请求者对象
AbstractRequest request1 = new Request1("Request1");
AbstractRequest request2 = new Request2("Request2");
AbstractRequest request3 = new Request3("Request3");
//总是从链式的首端发起请求
handler1.handleRequest(request1);
handler1.handleRequest(request2);
handler1.handleRequest(request3);
}
}
在实际开发中,经常会出现在一个DbusReceiver或者BroadcastReceiver中处理所有的Signals或者Actions,通过if…else来区分不同的signal或者Action,这样虽然简单,但是将所有的业务处理方法一个类中处理,不免会造成业务结构不清晰、代码冗长难懂。一种可行的方法就是通过责任链模式设计,将业务做拆分,将同一类型的业务放到一个单独类中处理,这样的处理能极大优化代码结构,使得业务逻辑更加清晰。DbusReceiver及BroadcastReceiver只作为消息的分发中心,每接收到一个信号或者action,将其交给责任链处理,各个责任链只负责处理自己关心的Signal或者Action。
对于Dbus的接收的责任链模式实现如下:
public abstract class AbsDbusHandler {
protected final Context mContext;
protected Handler mHandler = new Handler();
protected AbsDbusHandler nextHandler;
public AbsDbusHandler(Context context) {
mContext = context;
}
public abstract boolean handle(String sigName, int argLength, List<DbusObj> argList);
protected String getTag() {
return getClass().getSimpleName();
}
}
////处理Upgrade相关的Signal
public class UpgradeSignalsHandler extends AbsDbusHandler {
public UpgradeSignalsHandler(Context context) {
super(context);
}
@Override
public boolean handle(String sigName, int argLength, List<DbusObj> argList) {
if (sigName.equals(DbusSignal.SIGNAL_UPGEADE)) {
//do some thing
} else {
// other thing
}
return true;
} else {
if (nextHandler != null) {
return nextHandler.handle(sigName, argLength, argList);
} else {
return false;
}
}
}
}
//处理MetaSwitch相关的Signal
public class MetaSwitchSignalsHandler extends AbsDbusHandler {
private static Thread checkDevState;
public MetaSwitchSignalsHandler(Context context) {
super(context);
}
@Override
public boolean handle(String sigName, int argLength, List<DbusObj> argList) {
if (sigName.equals(DbusSignal.SIGNAL_METASWITCH_REQ_LOGIN)||
sigName.equals(DbusSignal.SIGNAL_METASWITCH_LOGIN_ERROR)) {
//do some thing
return true;
} else {
if (nextHandler != null) {
return nextHandler.handle(sigName, argLength, argList);
} else {
return false;
}
}
}
}
public class HandlerChainFactory {
private static AbsDbusHandler dbusHandler;
public static AbsDbusHandler productDbusChain(Context context) {
if(dbusHandler == null){
AbsDbusHandler metaSwitchSignalsHandler = new MetaSwitchSignalsHandler(context);
AbsDbusHandler audioSignalsHandler = new AudioSignalsHandler(context);
AbsDbusHandler upgradeSignalsHandler = new UpgradeSignalsHandler(context);
metaSwitchSignalsHandler.nextHandler = audioSignalsHandler;
audioSignalsHandler.nextHandler = upgradeSignalsHandler;
dbusHandler = metaSwitchSignalsHandler;
}
return dbusHandler;
}
private DbusCallback dbusCallback = new DbusCallback() {
@Override
public void onCallback(int sigId, String sigName, int argNum, List<DbusObj> argList) {
if (!getDbusHandler().handle(sigName, argNum, argList)) {
//责任没有处理的信号在这里处理
}
}
};
对于Action的接收的责任链模式实现:
基本思路和Dbus Signal处理类似,Receiver只是作为一个消息分发中心,每次接收到一个Intent,将其传入到责任链中进行处理。
责任链中一个处理者对象,其中只有两个行为,一是处理请求,二是将请求转送给下一个节点,不允许某个处理者对象在处理了请求后又将请求转送给上一个节点的情况。对于一条责任链来说,一个请求最终只有两种情况,一是被某个处理对象所处理,另一个是所有对象均未对其处理,前一种情况称该责任链为纯的责任链,对于后一种情况称为不纯的责任链,实际应用中,多为不纯的责任链。
责任链在Android源码中比较类似的实现莫过于View的事件分发处理,对于触摸事件,Android总是从VIewTree最顶端,从上而下处理,具体处理流程主要通过dispatchTouchEvent
、onTouchEvent
等函数处理,具体可以查看相关源码。ViewGroup事件投递的递归调用类似一条责任链,一旦其寻找到责任者,那么将有责任者持有并消费掉该次事件,具体体现在View的onTouchEvent方法中返回值的设置,如果onTouchEvent返回False,那么意味着当前View不会是该次事件的责任人,将不会对其持有:如果为true则相反,此时View会持有该事件并不再向外传递。
另外,著名的OKHttp3框架及Netty NIO框架也都使用了责任链模式设计。OkHttp3中Interceptor以及Netty中ChannelInboundHandlerAdapter都是责任链模式设计的典型。那么可以总结为责任链模式是处理数据流比较好的模式设计。
附一张OkHttp实现原理图
如果你愿意,所有的if…else语句及switc…case语句你都可以使用责任链模式进行改造,但是大部分情况下,这样做都是不必要的。而只有当过多的if…else分支导致代码难以维护时,考虑使用责任链模式进行业务拆分。