Java Design Patterns - Chain of Responsibility Pattern

1. Definition

The Chain of Responsibility pattern is a behavioral design pattern that allows you to send a request down a processing chain, and each processor can then process it and then pass it on to the next processor when it's done.

  • You can control the order in which requests are processed
  • The single responsibility principle can decouple the classes that initiate operations and perform operations
  • The principle of opening and closing, you can add other processing classes without modifying the original business code
  • There is no guarantee that every handler can execute
  • The efficiency is not very good, if you don’t pay attention when calling, there will be various problems

2. Usage scenarios

  • When multiple handlers must be executed sequentially, consider using the Chain of Responsibility pattern
  • If the order of handlers and their order must change at runtime, consider using the Chain of Responsibility pattern

Practical application:

  • Apache Tomcat's processing of Encoding encoding processing
  • Interceptors and filter chains in SpringBoot
  • Processing chain in netty
  • Payment risk control mechanism
  • log processing level

3. Simple application in Java

scenes to be used:

Taking the leave application system as an example, the team leader → director → minister forms a chain
. After the employee submits the leave application, the request will be passed along this chain until there is an object that can handle it.
A 5-day leave application, first arrives at the team leader;
the team leader has no authority to approve, and passes the request to his superior (director);
the director has authority to approve, so he agrees to the leave application
as the sender of the request, and the staff does not need to care about the final decision. Who approves, only needs to submit a request

3.1 Abstract processing interface


/**
 * @Author charles.yao
 * @Description 抽象处理者
 * @Date 2022/12/21 15:32
 */
public interface Hanlder {
    /**
     * 处理员工请假天数
     * @param name
     * @param holidayDay
     */
    public abstract void handleRequest(String name, Integer holidayDay);
}

3.2 Create three specific processors, the team leader, the director, and the minister, to realize the specific processing logic


/**
 * @Author charles.yao
 * @Description 组长处理者
 * @Date 2022/12/21 15:34
 */
public class PmHandler extends Hanlder {

    @Override
    public void handleRequest(String name, Integer holidayDay) {
        if (holidayDay <= 3) {
            System.out.println(name + "组长已经批准假期");
        } else {
            if (getNext() != null) {
                getNext().handleRequest(name,holidayDay);
            }else {
                System.out.println("请假天数太多,申请被驳回");
            }
        }

    }
}


/**
 * @Author charles.yao
 * @Description 部门经理处理者
 * @Date 2022/12/21 15:37
 */
public class MinisterHandler extends Hanlder{
    @Override
    public void handleRequest(String name, Integer holidayDay) {
        if (holidayDay <= 15) {
            System.out.println(name + "部门经理已经批准假期");
        } else {
            if (getNext() != null) {
                getNext().handleRequest(name,holidayDay);
            }else {
                System.out.println("请假天数太多,申请被驳回");
            }
        }
    }
}



/**
 * @Author charles.yao
 * @Description 总监处理者
 * @Date 2022/12/21 15:37
 */
public class DirectorHandler extends Hanlder{
    @Override
    public void handleRequest(String name, Integer holidayDay) {
        if (holidayDay <= 7) {
            System.out.println(name + "总监已经批准假期");
        } else {
            if (getNext() != null) {
                getNext().handleRequest(name,holidayDay);
            }else {
                System.out.println("请假天数太多,申请被驳回");
            }
        }
    }
}

test class


/**
 * @Author charles.yao
 * @Description
 * @Date 2022/12/21 15:39
 */
public class OaTest1 {
    public static void main(String[] args) {
        Hanlder pmHandler = new PmHandler();
        Hanlder directorHandler = new DirectorHandler();
        Hanlder ministerHandler = new MinisterHandler();
        pmHandler.setNext(directorHandler);
        directorHandler.setNext(ministerHandler);
        pmHandler.handleRequest("张三",14);

    }
}

operation result

张三部门经理已经批准假期

Through the above simple small demo, we will find a series of problems: if the specific handlers need to be increased, decreased or adjusted order, it will involve the adjustment and reconstruction of the entire chain of responsibility, but will increase unnecessary workload, we will carry out the above writing Improvement, the improvement is as follows,

    • Cancel the next reference in the abstract handler
    • Separate chain of responsibility class:
      • Provide the add method to add specific handlers, and build an invisible chain of responsibility based on List;
      • Implement the request processing method of the abstract handler, and traverse the specific handlers in the responsibility chain to realize the delivery and processing of the request
// 抽象处理者
public interface Handler {
    public abstract void handleRequest(String name, int days);
}

// 具体处理者
public class PMHandler implements Handler {
    @Override
    public void handleRequest(String name, int days) {
        if (days <= 3) {
            System.out.println(name +",组长已经同意您的请假审批!");
        }
    }
}

public class DirectorHandler implements Handler {
    @Override
    public void handleRequest(String name, int days) {
        if (days <= 7) {
            System.out.println(name + ",中心总监已经同意您的请假审批");
        }
    }
}

public class MinisterHandler implements Handler {
    @Override
    public void handleRequest(String name, int days) {
        if (days <= 15) {
            System.out.println(name + ",部长已经同意您的请假审批");
        }
    }
}

// 责任链类
public class HandlerChain implements Handler {
    private List<Handler> handlerList;

    public HandlerChain() {
        this.handlerList = new ArrayList<>();
    }

    public HandlerChain addHandler(Handler handler) {
        handlerList.add(handler);
        return this;
    }


    @Override
    public void handleRequest(String name, int days) {
        for (Handler handler : handlerList) {
            handler.handleRequest(name, days);
        }
    }
}

// 客户类
public class OASystem {
    public static void main(String[] args) {
        // 创建具体处理者
        Handler pm = new PMHandler();
        Handler director = new DirectorHandler();
        Handler minister = new MinisterHandler();
        // 构建责任链
        HandlerChain chain = new HandlerChain()
                .addHandler(pm)
                .addHandler(director)
                .addHandler(minister);

        // 使用责任链
        chain.handleRequest("王二", 10);
    }
}

Then we use springboot to use the chain of responsibility mode,

scenes to be used:

The user has to verify the work before placing an order, and obtain the user's order status in order.

Through seqId, check whether the customer has repeatedly placed an
order Check whether the request parameter is legal, and obtain the customer's bank account
Check whether the bank account is legal, call the banking system to check whether the bank account balance meets the order amount

Order Entity:


/**
 * @Author charles.yao
 * @Description 订单实体类
 * @Date 2023/1/28 14:58
 */
@Data
public class OrderContext {

    /**
     * 请求唯一序列ID
     */
    private String seqId;

    /**
     * 用户ID
     */
    private String userId;

    /**
     * 产品skuId
     */
    private Long skuId;

    /**
     * 下单数量
     */
    private Integer amount;

    /**
     * 用户收货地址ID
     */
    private String userAddressId;
    
}

Order verification abstract interface OrderHandleIntercept


/**
 * @Author charles.yao
 * @Description 订单处理结果类
 * @Date 2023/1/28 15:04
 */
public interface OrderHandleIntercept {
    /**
     * 指定处理顺序
     * @return
     */
    int sort();

    /**
     * 订单处理
     * @param orderContext
     * @return
     */
    OrderAddContext handle(OrderAddContext orderContext);
}

Logic verification for repeated orders


/**
 * @Author charles.yao
 * @Description 用于重复下单的逻辑验证
 * @Date 2023/1/28 15:24
 */
@Component
public class RepeatOrderHandleInterceptService implements OrderHandleIntercept{
    @Override
    public int sort() {

        return 1;
    }

    @Override
    public OrderAddContext handle(OrderAddContext orderContext) {
        System.out.println("通过orderId 校验客户是否重复下单");
        return orderContext;
    }
}

Used to verify whether the request parameters are legal


/**
 * @Author charles.yao
 * @Description 用于验证请求参数是否合法
 * @Date 2023/1/28 15:28
 */
@Component
public class ValidOrderHandleInterceptService implements OrderHandleIntercept{
    @Override
    public int sort() {
        return 2;
    }

    @Override
    public OrderAddContext handle(OrderAddContext orderContext) {
        System.out.println("检查请求参数,是否合法,并且获取客户的银行账户");
        return orderContext;
    }
}

Used to check whether the customer's account balance is sufficient

/**
 * @Author charles.yao
 * @Description 用于检查客户账户余额是否充足
 * @Date 2023/1/28 15:31
 */
@Component
public class BankOrderHandleInterceptService implements OrderHandleIntercept{
    @Override
    public int sort() {
        return 3;
    }

    @Override
    public OrderAddContext handle(OrderAddContext orderContext) {
        System.out.println("检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额");
        return orderContext;
    }
}

Order Validation Manager


/**
 * @Author charles.yao
 * @Description 订单验证管理器
 * @Date 2023/1/28 15:49
 */
@Component
public class OrderHandleChainService implements ApplicationContextAware {
    private List<OrderHandleIntercept> handleList = new ArrayList<>();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, OrderHandleIntercept> orderHandleInterceptMap = applicationContext.getBeansOfType(OrderHandleIntercept.class);
        handleList = orderHandleInterceptMap.values().stream()
                .sorted(Comparator.comparing(OrderHandleIntercept::sort))
                .collect(Collectors.toList());

    }

    public OrderAddContext execute(OrderAddContext context) {
        for (OrderHandleIntercept orderHandleIntercept : handleList) {
            orderHandleIntercept.handle(context);
        }
        return context;
    }
}

test class


/**
 * @Author charles.yao
 * @Description 订单测试类
 * @Date 2023/1/28 16:07
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class CalculatorServiceTest {

    @Autowired
    private OrderHandleChainService orderHandleChainService;

    @Test
    public void test(){
        orderHandleChainService.execute(new OrderAddContext());
    }
}

Test Results

2023-01-28 16:10:01.484  INFO 38155 --- [           main] c.y.d.c.CalculatorServiceTest            : Starting CalculatorServiceTest using Java 1.8.0_212 on localhost with PID 38155 (started by yaoyonghao in /Users/yaoyonghao/Documents/workProject/design-pattern)
2023-01-28 16:10:01.487  INFO 38155 --- [           main] c.y.d.c.CalculatorServiceTest            : No active profile set, falling back to 1 default profile: "default"
2023-01-28 16:10:02.540  INFO 38155 --- [           main] c.y.d.c.CalculatorServiceTest            : Started CalculatorServiceTest in 1.548 seconds (JVM running for 3.081)
通过orderId 校验客户是否重复下单
检查请求参数,是否合法,并且获取客户的银行账户
检查银行账户是否合法,调用银行系统检查银行账户余额是否满足下单金额

Of course, you can also control the order of execution through the @Order() annotation

Guess you like

Origin blog.csdn.net/CharlesYooSky/article/details/128779448