当前位置:网站首页>Yesterday, Alibaba senior wrote a responsibility chain model, and there were countless bugs
Yesterday, Alibaba senior wrote a responsibility chain model, and there were countless bugs
2022-07-02 18:41:00 【InfoQ】
background
What is the chain of responsibility

Use scenarios
- Multi conditional process judgment : Access control
- ERP System process approval : The general manager 、 Personnel manager 、 project manager
- Java The underlying implementation of the filter Filter
| Counter example
- The game has a total of 3 A level
- Entering the second level requires the game score of the first level to be greater than or equal to 80
- Entering the third level requires the game score of the second level to be greater than or equal to 90
// The first level
public class FirstPassHandler {
public int handler(){
System.out.println(" The first level -->FirstPassHandler");
return 80;
}
}
// The second level
public class SecondPassHandler {
public int handler(){
System.out.println(" The second level -->SecondPassHandler");
return 90;
}
}
// The third level
public class ThirdPassHandler {
public int handler(){
System.out.println(" The third level -->ThirdPassHandler, This is the last level ");
return 95;
}
}
// client
public class HandlerClient {
public static void main(String[] args) {
FirstPassHandler firstPassHandler = new FirstPassHandler();// The first level
SecondPassHandler secondPassHandler = new SecondPassHandler();// The second level
ThirdPassHandler thirdPassHandler = new ThirdPassHandler();// The third level
int firstScore = firstPassHandler.handler();
// The score of the first level is greater than or equal to 80 Then enter the second level
if(firstScore >= 80){
int secondScore = secondPassHandler.handler();
// The score of the second level is greater than or equal to 90 Then enter the second level
if(secondScore >= 90){
thirdPassHandler.handler();
}
}
}
} if( The first 1 Pass off ){
// The first 2 Turn off game
if( The first 2 Pass off ){
// The first 3 Turn off game
if( The first 3 Pass off ){
// The first 4 Turn off game
if( The first 4 Pass off ){
// The first 5 Turn off game
if( The first 5 Pass off ){
// The first 6 Turn off game
if( The first 6 Pass off ){
//...
}
}
}
}
}
} | Preliminary modification
public class FirstPassHandler {
/**
* The next level of the first level is The second level
*/
private SecondPassHandler secondPassHandler;
public void setSecondPassHandler(SecondPassHandler secondPassHandler) {
this.secondPassHandler = secondPassHandler;
}
// Score in this level game
private int play(){
return 80;
}
public int handler(){
System.out.println(" The first level -->FirstPassHandler");
if(play() >= 80){
// fraction >=80 And the next level exists before entering the next level
if(this.secondPassHandler != null){
return this.secondPassHandler.handler();
}
}
return 80;
}
}
public class SecondPassHandler {
/**
* The next level of the second level is The third level
*/
private ThirdPassHandler thirdPassHandler;
public void setThirdPassHandler(ThirdPassHandler thirdPassHandler) {
this.thirdPassHandler = thirdPassHandler;
}
// Score in this level game
private int play(){
return 90;
}
public int handler(){
System.out.println(" The second level -->SecondPassHandler");
if(play() >= 90){
// fraction >=90 And the next level exists before entering the next level
if(this.thirdPassHandler != null){
return this.thirdPassHandler.handler();
}
}
return 90;
}
}
public class ThirdPassHandler {
// Score in this level game
private int play(){
return 95;
}
/**
* This is the last pass , So there's no next level
*/
public int handler(){
System.out.println(" The third level -->ThirdPassHandler, This is the last level ");
return play();
}
}
public class HandlerClient {
public static void main(String[] args) {
FirstPassHandler firstPassHandler = new FirstPassHandler();// The first level
SecondPassHandler secondPassHandler = new SecondPassHandler();// The second level
ThirdPassHandler thirdPassHandler = new ThirdPassHandler();// The third level
firstPassHandler.setSecondPassHandler(secondPassHandler);// The next level of the first level is the second level
secondPassHandler.setThirdPassHandler(thirdPassHandler);// The next level of the second level is the third level
// explain : Because the third level is the last level , So there's no next level
// Start calling the first level Whether each level enters the next level Judge in each level
firstPassHandler.handler();
}
} | shortcoming
- Each level has a member variable of the next level and is different , It's inconvenient to form a chain
- The extensibility of the code is very bad
| Responsibility chain transformation
- Abstract processor (Handler) role : Define an interface to process requests , Contains abstract processing methods and a subsequent connection .
- Specific handler (Concrete Handler) role : Implement the processing methods of the abstract processor , Determine whether the request can be processed , If the request can be processed, process , Otherwise, forward the request to its successor .
- Customer class (Client) role : Create a processing chain , And submit the request to the specific handler object of the chain head , It doesn't care about processing details and the delivery of requests .

public abstract class AbstractHandler {
/**
* The next level uses the current abstract class to receive
*/
protected AbstractHandler next;
public void setNext(AbstractHandler next) {
this.next = next;
}
public abstract int handler();
}
public class FirstPassHandler extends AbstractHandler{
private int play(){
return 80;
}
@Override
public int handler(){
System.out.println(" The first level -->FirstPassHandler");
int score = play();
if(score >= 80){
// fraction >=80 And the next level exists before entering the next level
if(this.next != null){
return this.next.handler();
}
}
return score;
}
}
public class SecondPassHandler extends AbstractHandler{
private int play(){
return 90;
}
public int handler(){
System.out.println(" The second level -->SecondPassHandler");
int score = play();
if(score >= 90){
// fraction >=90 And the next level exists before entering the next level
if(this.next != null){
return this.next.handler();
}
}
return score;
}
}
public class ThirdPassHandler extends AbstractHandler{
private int play(){
return 95;
}
public int handler(){
System.out.println(" The third level -->ThirdPassHandler");
int score = play();
if(score >= 95){
// fraction >=95 And the next level exists before entering the next level
if(this.next != null){
return this.next.handler();
}
}
return score;
}
}
public class HandlerClient {
public static void main(String[] args) {
FirstPassHandler firstPassHandler = new FirstPassHandler();// The first level
SecondPassHandler secondPassHandler = new SecondPassHandler();// The second level
ThirdPassHandler thirdPassHandler = new ThirdPassHandler();// The third level
// Compared with the unchanged client code above , Only here set Method changes , Everything else is the same
firstPassHandler.setNext(secondPassHandler);// The next level of the first level is the second level
secondPassHandler.setNext(thirdPassHandler);// The next level of the second level is the third level
// explain : Because the third level is the last level , So there's no next level
// Start at the first level
firstPassHandler.handler();
}
} | Chain of responsibility factory transformation

public enum GatewayEnum {
// handlerId, Interceptor name , Fully qualified class name ,preHandlerId,nextHandlerId
API_HANDLER(new GatewayEntity(1, "api Interface current limiting ", "cn.dgut.design.chain_of_responsibility.GateWay.impl.ApiLimitGatewayHandler", null, 2)),
BLACKLIST_HANDLER(new GatewayEntity(2, " black block ", "cn.dgut.design.chain_of_responsibility.GateWay.impl.BlacklistGatewayHandler", 1, 3)),
SESSION_HANDLER(new GatewayEntity(3, " User session interception ", "cn.dgut.design.chain_of_responsibility.GateWay.impl.SessionGatewayHandler", 2, null)),
;
GatewayEntity gatewayEntity;
public GatewayEntity getGatewayEntity() {
return gatewayEntity;
}
GatewayEnum(GatewayEntity gatewayEntity) {
this.gatewayEntity = gatewayEntity;
}
}
public class GatewayEntity {
private String name;
private String conference;
private Integer handlerId;
private Integer preHandlerId;
private Integer nextHandlerId;
}
public interface GatewayDao {
/**
* according to handlerId Get configuration items
* @param handlerId
* @return
*/
GatewayEntity getGatewayEntity(Integer handlerId);
/**
* Get the first handler
* @return
*/
GatewayEntity getFirstGatewayEntity();
}
public class GatewayImpl implements GatewayDao {
/**
* initialization , The configured in the enumeration handler Initialize to map in , Easy access
*/
private static Map<Integer, GatewayEntity> gatewayEntityMap = new HashMap<>();
static {
GatewayEnum[] values = GatewayEnum.values();
for (GatewayEnum value : values) {
GatewayEntity gatewayEntity = value.getGatewayEntity();
gatewayEntityMap.put(gatewayEntity.getHandlerId(), gatewayEntity);
}
}
@Override
public GatewayEntity getGatewayEntity(Integer handlerId) {
return gatewayEntityMap.get(handlerId);
}
@Override
public GatewayEntity getFirstGatewayEntity() {
for (Map.Entry<Integer, GatewayEntity> entry : gatewayEntityMap.entrySet()) {
GatewayEntity value = entry.getValue();
// There is no last one handler Is the first
if (value.getPreHandlerId() == null) {
return value;
}
}
return null;
}
}
public class GatewayHandlerEnumFactory {
private static GatewayDao gatewayDao = new GatewayImpl();
// Provide static methods , Get the first one handler
public static GatewayHandler getFirstGatewayHandler() {
GatewayEntity firstGatewayEntity = gatewayDao.getFirstGatewayEntity();
GatewayHandler firstGatewayHandler = newGatewayHandler(firstGatewayEntity);
if (firstGatewayHandler == null) {
return null;
}
GatewayEntity tempGatewayEntity = firstGatewayEntity;
Integer nextHandlerId = null;
GatewayHandler tempGatewayHandler = firstGatewayHandler;
// Iterate through all handler, And link them
while ((nextHandlerId = tempGatewayEntity.getNextHandlerId()) != null) {
GatewayEntity gatewayEntity = gatewayDao.getGatewayEntity(nextHandlerId);
GatewayHandler gatewayHandler = newGatewayHandler(gatewayEntity);
tempGatewayHandler.setNext(gatewayHandler);
tempGatewayHandler = gatewayHandler;
tempGatewayEntity = gatewayEntity;
}
// Return to the first handler
return firstGatewayHandler;
}
/**
* Reflection materializes the specific handler
* @param firstGatewayEntity
* @return
*/
private static GatewayHandler newGatewayHandler(GatewayEntity firstGatewayEntity) {
// Gets the fully qualified class name
String className = firstGatewayEntity.getConference();
try {
// According to the fully qualified class name , Load and initialize the class , The static segment of this class will be initialized
Class<?> clazz = Class.forName(className);
return (GatewayHandler) clazz.newInstance();
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
e.printStackTrace();
}
return null;
}
}
public class GetewayClient {
public static void main(String[] args) {
GetewayHandler firstGetewayHandler = GetewayHandlerEnumFactory.getFirstGetewayHandler();
firstGetewayHandler.service();
}
} Conclusion
边栏推荐
- In early summer, Kaiyuan magic changed an electric mosquito racket with killing sound effect!
- QT official example: QT quick controls - Gallery
- 微信小程序视频分享平台系统毕业设计毕设(2)小程序功能
- Steamos 3.3 beta release, steam deck Chinese keyboard finally came
- Win10 uninstall CUDA
- Matlab中弧度转角度、角度转弧度
- Pychar modify pep8 e501 line too long > 0 characters
- iframe嵌套详解
- 元宇宙链游系统开发(逻辑开发)丨链游系统开发(详细分析)
- Wechat applet video sharing platform system graduation design completion (8) graduation design thesis template
猜你喜欢

UE4 用spline画正圆

再放寬!這些應届生,可直接落戶上海

Nm01 function overview and API definition of nm module independent of bus protocol

微信小程序视频分享平台系统毕业设计毕设(5)任务书

Picking up the camera is the best artistic healing

NM01-独立于总线协议的NM模块功能概述与API定义

阿里三面被面试官狂问Redis,简历上再也不敢写'精通'了

exness深度好文:动性系列-黄金流动性实例分析(五)

Leetcode interview question 16.11 Diving board

微信小程序视频分享平台系统毕业设计毕设(7)中期检查报告
随机推荐
Wechat applet video sharing platform system graduation design completion (8) graduation design thesis template
How to use PS to extract image color and analyze color matching
Ue4 dessine un cercle avec une ligne de contour
SteamOS 3.3 Beta 发布,Steam Deck 中文键盘终于来了
QT official example: QT quick controls - Gallery
能解决80%故障的排查思路
Rte11 interrupt decoupling function
promise 和 Observable 的区别
After 22 years in office, the father of PowerShell will leave Microsoft: he was demoted by Microsoft for developing PowerShell
Leetcode interview question 16.11 Diving board
Typical application of "stack" - expression evaluation (implemented in C language)
A4988 and 42 stepper motors
【愚公系列】2022年07月 Go教学课程 001-Go语言前提简介
阿里三面被面试官狂问Redis,简历上再也不敢写'精通'了
Aptos tutorial - participate in the official incentive testing network (ait2 incentive testing network)
Leetcode interview question 17.04 Vanishing numbers
300+ documents! This article explains the latest progress of multimodal learning based on transformer
Memory mapping of QT
Architecture design - ID generator "suggestions collection"
微信小程序视频分享平台系统毕业设计毕设(1)开发概要