责任型模式包括:责任链模式、单例(体)模式、观察者模式、中介者模式、代理模式、享元模式。
责任链模式(Chain of Responsibility)
定义
是一种对象的的行为模式。它使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
发出请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统在不影响客户端的情况下动态地重新组织链和分配责任。
数据结构
责任链可能是一条直线、一个环链、或者树的一部分。链的拓扑结构单连通和多连通都可以。责任链模式往往是建立在现有基础之上的,所以链的结构和组成并不由责任链模式本身决定。
类图
- 抽象处理角色(Handler):定义出一个处理请求的接口(有需要也可以定义返回下家引用的方法),抽象方法handleRequest()规范了子类处理请求的操作。
- 具体处理者角色(ConcreteHandler):处理接到请求后,可以选择将请求处理掉,或者传给下家。
优点
- 降低耦合度。它将请求的发送者和接收者解耦。
- 简化了对象。使得对象不需要知道链的结构也可以完成请求。
- 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
- 增加新的请求处理类很方便。
缺点
- 不能保证请求一定被接收。
- 在找到正确的处理对象之前,所有的条件判定都要执行一遍,当责任链过长时,可能会引起性能的问题。
纯的和不纯的责任链:
纯的:要求一个具体的处理者对象只能在两个行为中选择一个:承担责任或把责任传给下家;不存在承担了责任又把责任传递给下家。一个请求必须被一个处理者对象所接受。
不纯的:可以既承担责任又传递责任。请求也可以不被任何接收端对象处理。
纯的责任链模式实际例子很难找到,一般看到的都是不纯的。
使用场景
- 系统中已有一个由处理者对象组成的链。
- 当有多个的处理者对象会处理一个请求,而且事先不知道哪个对象处理。
- 系统发出的请求不明显指定是哪一个处理者对象处理。
- 当处理一个请求的处理者对象集合需要动态地指定时。
一个系统的审批需要多个对象才能完成处理的情况;代码中存在多个if-else语句的情况下,此时可以考虑使用责任链模式来对代码进行重构;如审批系统(请假、各种人事签字)、击鼓传花。
注:流程传递和这个还不太一样。
首先,责任链模式要求同一时间内,命令只可以传递给一个下家,工作流中会有给部门派工,会有很多处理对象,这个得结合权限系统。
其次:工作流中所有的中间环节对象都是即处理了请求也把任务进行了传递。
测试代码
//客户端,向链上的具体处理者对象提交请求
public class Client {
public static void main(String[] args) {
//在实际应用中这些对应一个个实体(审批系统的组长,班长,排长),这部分可以考虑提到配置文件中。
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
Handler handlerC = new ConcreteHandlerC();
//设置责任链
handlerA.setSuccessor(handlerB);
handlerB.setSuccessor(handlerC);
//发起请求
int[] requests = { 2, 14, 5, 6, 8, 23, 12, 21 };
for (int i : requests) {
handlerA.handleRequest(i);
}
}
}
//处理请求的接口
public abstract class Handler {
protected Handler successor;
public void setSuccessor(Handler successor) {
this.successor = successor;
}
public abstract void handleRequest(int request);
}
//具体处理者类,处理它所负责的请求,可访问它的后继者,如果可处理该请求,则处理,否则转给它的后继者处理
public class ConcreteHandlerA extends Handler {
@Override
public void handleRequest(int request) {
if (request >= 0 && request <= 10) {
System.out.println(this.getClass().getName() + "处理了请求" + request);
} else if (successor != null) {
successor.handleRequest(request);
}
}
}
public class ConcreteHandlerB extends Handler {
@Override
public void handleRequest(int request) {
if (request > 10 && request <= 20) {
System.out.println(this.getClass().getName() + "处理了请求" + request);
} else if (successor != null) {
successor.handleRequest(request);
}
}
}
public class ConcreteHandlerC extends Handler {
@Override
public void handleRequest(int request) {
if (request > 20 && request <= 30) {
System.out.println(this.getClass().getName() + "处理了请求" + request);
} else if (successor != null) {
successor.handleRequest(request);
}
}
}