(1)设计模式之责任链模式

目录

一、定义 

二、使用场景

三、代码示例

1. 示例场景-闯关游戏:

2. 思路分析:

3. 责任链模式的基本组成:

4. 代码示例

四、真实业务中的改造


一、定义 

将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。
以上定义来自《设计模式之美》

二、使用场景

  • 多条件流程判断:权限控制

  • 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返回。

实际开发中,我们要根据不同业务场景将某些设计模式做适配。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值