职责链模式

职责链模式概述

职责链模式解决的问题

案例 : 一个贷款审批案例,假设贷款额度小于5万时由客户负责人审核放款,当贷款额度大于5万小于10万时由项目经理负责审批,当贷款额度大于10万小于20万时由审核团队来审批
问题 : 由谁来审批是通过贷款金额大小来决定的,在传统模式中,通常会使用 if - else等相关流程判断语句,来判断金额大小,获取到审批的负责人,会出现大量的条件转移语句,影响代码可读性,假设后续更改了审批规则,则需要更改这个的代码违反ocp原则

角色分析

  • 抽象处理者 Handler : 定义了处理请求的接口,同时持有另外一个处理者
  • 具体处理者 ConcreteHandler : 一般存在多个,实现抽象处理者,根据自己的责任重写实现处理的功能方法,可以将多个具体处理者看为是不同级别的责任人,每一个具体处理者都会持有一个下一级的具体处理者,当前请求这个处理者若可以处理则调用自己的处理方法进行处理, 当判断无法处理时,会将请求交个持有的下一级具体处理者进行处理,依次类推到最后抛出异常等
  • 注意点: 明确不同级别处理者持有的下一个级别的处理者,在接收请求前创建设置完成,有接收请求的处理者内部自行判断是否能够处理
  • 自己理解: 就是创建不同职责的类,每一个职责类持有下一个职责类对象,实现功能的方法根据职责的不同定义在职责类中,在职责类中只判断当前职责类是否能处理,如果能处理则处理,否则交给持有的下一级别的职责类对象进行处理,形成一个环

职责链模式优点

  • 职责链模式的最主要功能就是:动态组合,请求者和接受者解耦。
  • 请求者和接受者松散耦合:请求者不需要知道接受者,也不需要知道如何处理。每个职责对象只负责自己的职责范围,其他的交给后继者。各个组件间完全解耦。
  • 动态组合职责:职责链模式会把功能分散到单独的职责对象中,然后在使用时动态的组合形成链,从而可以灵活的分配职责对象,也可以灵活的添加改变对象职责。

代码示例

上面的审批贷款案例通过职责链模式实现

  1. 创建抽象处理者
abstract  class Approver{
    private Approver approver; //下一个等级的处理者
    private String name; //处理者姓名

    public Approver(String name){
        this.name = name;
    }

    //获取下一个级别的处理者
    public Approver getApprover() {
        return approver;
    }
    //设置下一个级别的处理者
    public void setApprover(Approver approver) {
        this.approver = approver;
    }

    //处理审批请求的抽象方法,有具体处理者根据
    //自己的责任进行具体实现,传递请求对象,通
    //过请求对象可以获取到用来判断是否有职责处理的数据
    public abstract void processRequest(PurchaseRequest purchaseRequest);

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
  1. 创建具体处理者,此处有三个"客户负责人",“项目经理”,“审核会议”,具体处理者继承抽象处理者,持有下一个级别的处理者,根据自己的责任重写处理方法,在方法中判断当前处理者是否能处理这个审批请求,当当前处理者无法处理时交由持有的下一个处理者进行处理
    客户负责人
class Principal extends Approver{

    public Principal(String name) {
        super(name);
    }

    @Override
    public void processRequest(PurchaseRequest purchaseRequest) {
        //当小于等于5万时,有当前"客户负责人"级别进行处理
        if(purchaseRequest.getPrice() <= 5){
            System.out.println("客户贷款金额为:"+purchaseRequest.getPrice()
                    +"万,由客户负责人:"+this.getName()+"负责审批处理");
        }else {
           //否则交由持有的下一个级别进行处理
            this.getApprover().processRequest(purchaseRequest);
        }
    }
}

项目经理

//项目经理处理者
class Manager extends Approver{

    public Manager(String name) {
        super(name);
    }

    @Override
    public void processRequest(PurchaseRequest purchaseRequest) {
        if(purchaseRequest.getPrice() <= 10){
            System.out.println("客户贷款金额为:"+purchaseRequest.getPrice()
                    +"万,由项目经理:"+this.getName()+"负责审批处理");
        }else {

            this.getApprover().processRequest(purchaseRequest);
        }
    }
}

审核会议(最终处理者)

class Conference extends Approver{

    public Conference(String name) {
        super(name);
    }

    @Override
    public void processRequest(PurchaseRequest purchaseRequest) {
        if(purchaseRequest.getPrice() <= 20){
            System.out.println("客户贷款金额为:"+purchaseRequest.getPrice()
                    +"万,由审核会议:"+this.getName()+"负责审批处理");
        }else {
            //最终级别处理者,当还是处理不了时抛出异常
            System.out.println("客户贷款金额为:"+purchaseRequest.getPrice()
                    +"万,金额太大抛出异常");
            //也可以设置交由下一个处理者处理
            //this.getApprover().processRequest(purchaseRequest);
        }
    }
}
  1. 调用测试,注意点,将请求交由具体处理者,在具体处理者中判断是否能够处理,在接收请求以前,就需要创建出所有处理者,并设置好处理者中持有的指定下个级别处理者
	public static void main(String[] args) {
        //注意点,在接收请求进行处理时,要设置好
        //每个处理者持有的下一个处理者
        Approver principal = new Principal("负责人小明");
        Approver manager = new Manager("项目经理小红");
        Approver conference = new Conference("贷款会议小组");

        //设置负责人级别,持有项目经理级别,当负责人无法处理时,交由项目经理处理
        principal.setApprover(manager);
        //设置项目经理级别,持有会议级别,当项目经理处理不了时,交由审核会议处理
        manager.setApprover(conference);
        //审核会议为最终级别,可以不设置,也可以设置形成闭环
        //conference.setApprover(principal);

        //创建请求对象,客户端请求
        PurchaseRequest purchaseRequest = new PurchaseRequest("贷款请求",21);
		
		//通过处理者处理,
        principal.processRequest(purchaseRequest);
    }

源码中的职责链模式使用案例

在 Spring 框架中,或权限框架中经常见到职责链模式,拦截器,权限校验等功能都是通过责任链来实现的,查看 javax.servlet .Filter 过滤器,该接口中有一个doFilter()方法,在我们实现过滤器时,通常要继承Filter接口重写doFilter()方法,此处的Filter就相当于一个抽象处理者,而具继承该接口实现子类就是具体处理者,doFilter()方法就是实际处理方法

业务与设计模式落地案例

  1. 职责链设计模式适用于有多个对象处理同一个请求的场景,这些对象可以按照顺序构成一条责任链,每个对象处理请求的方式不同,但是都可以根据请求的内容来判断是否自己需要处理。如果需要处理,则自己负责处理请求;否则就将请求传递给责任链中的下一个对象
  2. 网上购物平台的订单支付功能通过职责链设计模式实现
  3. 定义支付处理器接口,该接口包含了处理支付请求的方法
public interface PaymentHandler {
	//用于判断该处理器是否可以处理当前支付请求
    boolean canHandle(PaymentRequest request);
    //处理具体支付请求
    void handle(PaymentRequest request);
}
  1. 定义具体的支付处理器实现类,假设有3个处理器
@Component
public class AlipayHandler implements PaymentHandler {
    @Override
    public boolean canHandle(PaymentRequest request) {
        // 根据请求信息判断是否能够处理
        return "alipay".equals(request.getPaymentType());
    }

    @Override
    public void handle(PaymentRequest request) {
        // 处理支付请求
        System.out.println("使用支付宝处理支付请求:" + request.getAmount());
    }
}

@Component
public class WechatPayHandler implements PaymentHandler {
    @Override
    public boolean canHandle(PaymentRequest request) {
        // 根据请求信息判断是否能够处理
        return "wechatpay".equals(request.getPaymentType());
    }

    @Override
    public void handle(PaymentRequest request) {
        // 处理支付请求
        System.out.println("使用微信支付处理支付请求:" + request.getAmount());
    }
}

@Component
public class CreditCardHandler implements PaymentHandler {
    @Override
    public boolean canHandle(PaymentRequest request) {
        // 根据请求信息判断是否能够处理
        return "creditcard".equals(request.getPaymentType()) && request.getAmount() <= 1000;
    }

    @Override
    public void handle(PaymentRequest request) {
        // 处理支付请求
        System.out.println("使用信用卡处理支付请求:" + request.getAmount());
    }
}
  1. 定义PaymentController控制器,用于接收来自客户端的支付请求,并调用支付处理器处理请求
@RestController
@RequestMapping("/payment")
public class PaymentController {
    private final List<PaymentHandler> handlers;

    public PaymentController(List<PaymentHandler> handlers) {
        this.handlers = handlers;
    }

    @PostMapping("/")
    public String pay(@RequestBody PaymentRequest request) {
    	//循环遍历所有处理器,调用canHandle方法来判断是否能够处理请求
    	//如果找到匹配的处理器,调用handle方法来处理请求
        for (PaymentHandler handler : handlers) {
            if (handler.canHandle(request)) {
                handler.handle(request);
                return "success";
            }
        }
        return "no suitable handler found";
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值