当前位置:网站首页>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
边栏推荐
- SteamOS 3.3 Beta 发布,Steam Deck 中文键盘终于来了
- Troubleshooting ideas that can solve 80% of faults
- Ali was wildly asked by the interviewer on three sides. Redis dared not write 'proficient' on his resume anymore
- 工业软件讲堂-三维CAD设计软件的核心技术解析----讲坛第二次讲座
- sql训练2
- IPtable port redirection masquerade[easy to understand]
- 2020 Internet industry terminology
- Leetcode(81)——搜索旋转排序数组 II
- Implementation shadow introduction
- How to set vscode to delete the whole line shortcut key?
猜你喜欢

Leetcode(81)——搜索旋转排序数组 II

Relax again! These fresh students can settle directly in Shanghai

Qt官方示例:Qt Quick Controls - Gallery

Esp32-c3 introductory tutorial question ⑩ - error: implicit declaration of function 'ESP_ blufi_ close‘;

RDK simulation experiment

Pit encountered during installation of laravel frame

揭秘得物客服IM全链路通信过程

Leetcode interview question 16.17 Continuous sequence

再放宽!这些应届生,可直接落户上海
![[Yugong series] July 2022 go teaching course 001 introduction to go language premise](/img/f2/3b95f53d67cd1d1979163910dbeeb8.png)
[Yugong series] July 2022 go teaching course 001 introduction to go language premise
随机推荐
Wechat nucleic acid detection appointment applet system graduation design completion (5) task statement
微信小程序视频分享平台系统毕业设计毕设(7)中期检查报告
Use dosbox to run the assembly super detailed step "suggestions collection"
Détends - toi encore! Ces nouveaux étudiants peuvent s'installer directement à Shanghai
Leetcode 面试题 16.11. 跳水板
Leetcode interview question 16.17 Continuous sequence
微信小程序视频分享平台系统毕业设计毕设(1)开发概要
如何设置VSCode删除整行快捷键?
Leetcode interview question 17.01 Addition without plus sign
Troubleshooting ideas that can solve 80% of faults
链游系统开发(Unity3D链游开发详情)丨链游开发成熟技术源码
Please, stop painting star! This has nothing to do with patriotism!
Deep neural network Summary
Wechat nucleic acid detection appointment applet system graduation design completion (1) development outline
StretchDIBits函数
又一所双非改考408,会爆冷么?南昌航空大学软件学院
Architecture design - ID generator "suggestions collection"
Wechat applet video sharing platform system graduation design completion (6) opening defense ppt
@Component 拿不到dao层
Unity learning shader notes [81] simple color adjustment post-processing (brightness, saturation, contrast)