目录
一、定义
将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。
以上定义来自《设计模式之美》
二、使用场景
-
多条件流程判断:权限控制
-
ERP 系统流程审批:总经理、人事经理、项目经理
-
Java 过滤器的底层实现 Filter
三、代码示例
1. 示例场景-闯关游戏:
-
游戏一共 3 个关卡
-
进入第二关需要第一关的游戏得分大于等于 70
-
进入第三关需要第二关的游戏得分大于等于 90
2. 思路分析:
思考:每个关卡中都有下一关的成员变量,并且是不一样的,那么我们可以在关卡上抽象出一个父类或者接口,然后每个具体的关卡去继承或者实现。
3. 责任链模式的基本组成:
-
抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
-
具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
-
客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
4. 代码示例
抽象类:
/**
* 责任链模式--抽象处理者角色
*
*/
public abstract class AbstractHandler {
/**
* 下一关用当前抽象类来接收
*/
protected AbstractHandler next;
public void setNext(AbstractHandler next) {
this.next = next;
}
public abstract int handler();
}
链条上的各节点:
// 编写具体的处理器来继承AbstractHandler类
public class FirstPassHandler extends AbstractHandler {
private int play() {
return 80;
}
@Override
public int handler() {
System.out.println("第一关: FirstPassHandler.handler()");
int score = play();
if (score >= 70) {
// 有下一关
if (this.next != null) {
return this.next.handler();
}
}
return score;
}
}
public class SecondPassHandler extends AbstractHandler {
private int play() {
return 90;
}
@Override
public int handler() {
System.out.println("第二关: SecondPassHandler.handler()");
int score = play();
if (score >= 90) {
// 有下一关
if (this.next != null) {
return this.next.handler();
}
}
return score;
}
}
public class ThirdPassHandler extends AbstractHandler {
private int play() {
return 95;
}
@Override
public int handler() {
System.out.println("第三关: ThirdPassHandler.handler()");
int score = play();
if (score >= 95) {
// 有下一关
if (this.next != null) {
return this.next.handler();
}
}
return score;
}
}
客户端处理:
public class ChainHandlerClient {
public static void main(String[] args) {
// 第一关
FirstPassHandler firstPassHandler = new FirstPassHandler();
// 第二关
SecondPassHandler secondPassHandler = new SecondPassHandler();
// 第三关
ThirdPassHandler thirdPassHandler = new ThirdPassHandler();
firstPassHandler.setNext(secondPassHandler);
secondPassHandler.setNext(thirdPassHandler);
// 从第一个关卡开始
firstPassHandler.handler();
}
}
运行结果:
四、真实业务中的改造
框架中的这种思想,应用于真实业务中时就对应一些修改
举一个例子:
订单详情页中有很多模块,比如:地址模块、商品详情模块...
@Data
public class ItemInfo {
private Long itemId;
private String itemName;
}
@Data
public class SkuInfo {
private Long skuId;
private String skuName;
}
// 抽象方法
public abstract class AbstractDataHandler<T> {
protected abstract T doRequest(String query);
}
// 实现类
@Component
public class AddressInfoHandler extends AbstractDataHandler<ItemInfo> {
@Override
protected ItemInfo doRequest(String query) {
ItemInfo info = new ItemInfo();
info.setItemId(898989L);
info.setItemName("测试商品");
return info;
}
}
@Component
public class SkuInfoHandler extends AbstractDataHandler<SkuInfo> {
@Override
protected SkuInfo doRequest(String query) {
SkuInfo info = new SkuInfo();
info.setSkuId(12121212L);
info.setSkuName("测试SKU");
return info;
}
}
// 测试类
@RestController
public class ChainController {
@Autowired
private SkuInfoHandler skuInfoHandler;
@Autowired
private AddressInfoHandler itemInfoHandler;
@RequestMapping("/query")
public Map convertItemDetail() {
Map result = new HashMap();
result.put("skuInfoHandler", skuInfoHandler.doRequest("模拟数据请求"));
result.put("itemInfoHandler", itemInfoHandler.doRequest("模拟数据请求"));
System.out.println(JSON.toJSONString(result));
return result;
}
}
执行结果:
{
"skuInfoHandler":{
"skuId":12121212,
"skuName":"测试SKU"
},
"itemInfoHandler":{
"itemId":898989,
"itemName":"测试商品"
}
}
大家应该看出这其中的不一样了,这个例子中,我们并没有将handler向下传递,而是通过convertItemDetail方法将各模块封装起来,组成一个map返回。
实际开发中,我们要根据不同业务场景将某些设计模式做适配。