责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
在以下条件下可考虑使用Chain of Responsibility:
1 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
2 你想在不明确指定接受者的情况下,想过个对象中的一个提交一个请求。
3 可处理一个请求的对象集合应该被动态指定。
小栗子
很简单的例子,就是报销流程,项目经理<部门经理<总经理
其中项目经理报销额度不能大于500,则部门经理的报销额度是不大于1000,大于部分则需要总经理审核
package com.chain.responsibility;
public abstract class Handler {
// 职位级别
private double level = 0;
// 责任传递,下一个人责任人是谁
private Handler nextHanlder;
// 每个类都要说明一下自己能处理哪些请求
public Handler(int _level) {
this.level = _level;
}
// 处理请求
public final void handleMessage(Employee emp) {
if (emp.getType() == this.level) {
this.doHandler(emp);
} else {
if (this.nextHanlder != null) { // 有后续环节,才把请求往后递送
this.nextHanlder.handleMessage(emp);
} else { // 已经没有后续处理人了,不用处理了
System.out.println("-----------没地方请示了,不做处理!---------\n");
}
}
}
// 总经理审核处理
public final void handleCheck(Employee emp) {
if (randomBoolean()) {
System.out.println("总经理审核通过给予报销:" + emp.getFree());
} else {
System.out.println("总经理审核不通过不给予报销:" + emp.getFree() + "\n");
}
}
private boolean randomBoolean() {
return Math.random() < 0.5;
}
// 设置下一个环节
public void setNext(Handler _handler) {
this.nextHanlder = _handler;
}
public void setNextHanlder(Handler nextHanlder) {
this.nextHanlder = nextHanlder;
}
/** emp申请人 free报销费用 */
public abstract void doHandler(Employee emp);
}
package com.chain.responsibility;
public class Employee {
/*
* 通过一个int类型的参数来描述员工的职位状况 1---项目经理 2---部门经理 3---总经理
*/
private int type = 0;
// 请求报销费用
private double free;
public Employee(int type, double free) {
this.type = type;
this.free = free;
}
public Employee() {
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public double getFree() {
return free;
}
public void setFree(double free) {
this.free = free;
}
}
package com.chain.responsibility;
public class ProjectHandler extends Handler {
public ProjectHandler() {
super(1);
}
@Override
public void doHandler(Employee emp) {
System.out.println("---------项目经理申请报销-----------" );
if (emp.getFree() <= 500) {
System.out.println("给予报销:" + emp.getFree() + "\n");
} else {
// 总经理审核
super.handleCheck(emp);
}
}
}
package com.chain.responsibility;
public class DeptHandler extends Handler {
public DeptHandler() {
super(2);
}
@Override
public void doHandler(Employee emp) {
System.out.println("--------部门经理申请报销----------");
if (emp.getFree() <= 1000) {
System.out.println("给予报销:" + emp.getFree() + "\n");
} else {
super.handleCheck(emp);
}
}
}
package com.chain.responsibility;
public class GeneralHandler extends Handler {
public GeneralHandler() {
super(3);
}
@Override
public void doHandler(Employee emp) {
System.out.println("--------总经理申请报销--------");
System.out.println("总经理给予报销:" + emp.getFree() + "\n");
}
}
结果也正确,业务调用类Client 也不用去做判断到底是需要谁去处理,而且Handler 抽象类的子类以
后可以继续增加下去,只是我们这个传递链增加而已,调用类可以不用了解变化过程,甚至是谁在处理这
个请求都不用知道。
通用类图:
求,setNext 是设置当前环节怎么把不属于自己处理的请求扔给谁,对于这个类图我觉得需要改变,融合进
来模版方法模式,类图如下:
通过融合模版方法模式,各个实现类只要关注的自己业务逻辑就
成了,至于说什么事要自己处理,那就让父类去决定好了,也就是说父类实现了请求传递的功能,子类实
现请求的处理,符合单一职责法则,各个类只作一个动作或逻辑,也就是只有一个原因引起类的改变,我
建议大家在使用的时候用这种方法,好处是非常明显的了,子类的实现非常简单,责任链的建立也非常的
灵活。