工作中可能有这样的请求处理场景,例如假期审批,会根据申请假期的天数长短,由不同权限的主管者审批,但提交申请时总是提交给自己的直接主管,由直接主管来判断是否需要上升到更高权限的管理者来审批。类似场景可以描述为一个请求根据其内容由不同级别的处理者处理,申请入口总是最低级别的处理者。在客户端中处理此类请求,最简单直接的做法用if-else
语句遍询所有处理者,最终总能够被某一权限的处理者处理。这种做法的缺点是客户端责任太大,违背了单一职责原则,另外可扩展性也很差,当需要修改或删减处理者时,需要修改客户端代码。对于这种场景可以使用责任链模式实现,创建每一层级的处理者类,内部均实现一个处理方法,请求从最底层处理者开始,每一层级处理者处理请求时,如判断不在权限范围内,则向后继处理者传递该请求,直至最后一层。这种做法很好地实践了单一职责原则,由于每一层级处理者均为一类,对处理者的变化也有良好的扩展能力。
package com.yukiyama.pattern.behavior;
/**
* 责任链模式
*/
public class ResponsibilityChainDemo {
public static void main(String[] args) {
// 声明责任链上所有级别的处理者
// L1处理者有小于3天的请假审批权
Manager L1 = new L1Manager("一级主管");
// L2处理者有3到10天的请假审批权
Manager L2 = new L2Manager("二级主管");
// L3处理者有20天以内的请假审批权,超过则驳回
Manager L3 = new L3Manager("三级主管");
// 从低到高,每个层级的处理者设置自己的上级(后继)处理者
// 使请求能够从最低级处理者开始传递到最高级处理者
L1.setSuperior(L2);
L2.setSuperior(L3);
// 声明一个请求并设置请求的内容
Application app = new Application();
app.setDaysNum(2);
// 每次申请均只需由最低级处理者一级主管L1来执行申请
// 输出"一级主管批准2天请假申请。"
L1.apply(app);
app.setDaysNum(5);
// 输出“二级主管批准5天请假申请。”
L1.apply(app);
app.setDaysNum(15);
// 输出“三级主管批准15天请假申请。”
L1.apply(app);
app.setDaysNum(21);
// 输出“该请假申请天数为21天,三级主管驳回超过20天假期申请。”
L1.apply(app);
}
}
/**
* 抽象处理者类
* 持有一个name属性,并在有参构造器中初始化该属性。持有自己的后继处理者
* superior,通过普通方法setSuperior设置。定义了一个处理申请的抽象
* 方法apply(Application app)。
*/
abstract class Manager{
protected String name;
protected Manager superior;
public Manager(String name) {
this.name = name;
}
public void setSuperior(Manager superior) {
this.superior = superior;
}
public abstract void apply(Application app);
}
/**
* 具体处理者类
* 继承抽象处理者类,实现了抽象方法apply,根据申请内容的不同,不能处理时
* 调用后继处理者的apply方法交由后继处理者处理。
* 下例是最低级别的处理者L1。
*/
class L1Manager extends Manager{
public L1Manager(String name) {
super(name);
}
@Override
public void apply(Application app) {
if(app.getDaysNum() < 3) {
System.out.printf("%s批准%d天请假申请。\n", name, app.getDaysNum());
} else {
if(superior != null) {
superior.apply(app);
}
}
}
}
/**
* 具体处理者类
* 下例是L1的后继处理者L2。
*/
class L2Manager extends Manager{
public L2Manager(String name) {
super(name);
}
@Override
public void apply(Application app) {
if(app.getDaysNum() >= 3 && app.getDaysNum() <= 10) {
System.out.printf("%s批准%d天请假申请。\n", name, app.getDaysNum());
} else {
if(superior != null) {
superior.apply(app);
}
}
}
}
/**
* 具体处理者类
* 下例是L2的后继处理者L3。
*/
class L3Manager extends Manager{
public L3Manager(String name) {
super(name);
}
@Override
public void apply(Application app) {
if(app.getDaysNum() > 10 && app.getDaysNum() <= 20) {
System.out.printf("%s批准%d天请假申请。\n", name, app.getDaysNum());
} else {
System.out.printf("该请假申请天数为%d天,%s驳回超过20天假期申请。\n", app.getDaysNum(), name);
}
}
}
/**
* 请求类(可选)
* 当请求包含较多属性时,可以将请求封装成类。当请求比较简单如申请放假天数,
* 也可以只用基本数据类型。
*/
class Application{
private int daysNum;
public int getDaysNum() {
return daysNum;
}
public void setDaysNum(int daysNum) {
this.daysNum = daysNum;
}
}