What is the chain of responsibility model
Chain of responsibility mode is a design mode used to encapsulate process logic and facilitate extended development. With the structure of chain of responsibility mode and the powerful Spring framework, developers can adjust the chain order and delete or change at will.
The role of the chain of responsibility model
In daily business development, you might often check a parameter or filter a few objects, and your code will become bloated after various if(judgment){execute this branch logic}, and your colleagues will look like this over time.
Chain of responsibility model two best practices
Implement sequential verification based on responsibility chain mode
Requirements describe
Dog products: make a function, parameter verification, first determine whether it is empty, and then determine whether the length is less than 5, in the judgment of whether this parameter contains bad words.
You: That’s it?
Dog products: these first, you do first, there may be more logic in the future, the above verification function may be connected to the third party tools, it is hard to say.
You: I’m XXXXX
Code implementation
Define parameter validation abstract classes, specify behavior, and determine common logic for each chain
package com.example.Chain.config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class AbstractHandler { protected static final Logger logger = LoggerFactory.getLogger(AbstractHandler.class); /** * private AbstractHandler nextHandler; public void setNextHandler(AbstractHandler nextHandler) { this.nextHandler = nextHandler; } public AbstractHandler getNextHandler() { return nextHandler; } public void validate(String param) { boolean validate = doValidate(param); if (! validate){ return; } if (null! =getNextHandler()){getNextHandler().validate(param); }} @param param */ protected Boolean doValidate(String param); }Copy the code
Null judgment check chain
Note that I added an Order annotation to control the ioc loading Order to keep the verification logic in Order
package com.example.Chain.support; import com.example.Chain.config.AbstractHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; @Component @Order(1) public class EmptyCheckHandler extends AbstractHandler { protected static final Logger logger = LoggerFactory.getLogger(EmptyCheckHandler.class); @override protected Boolean doValidate(String param) {if (stringutils.isempty (param)){logger.info(" null "); return false; } return true; }}Copy the code
Length check chain
package com.example.Chain.support; import com.example.Chain.config.AbstractHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component @Order(2) public class LengthCheckHandler extends AbstractHandler { protected static final Logger logger = LoggerFactory.getLogger(LengthCheckHandler.class); @override protected Boolean doValidate(String param) {if (param.length() < 5) {logger.info(" current request parameter < 5 parameter value {}",param); return false; } return true; }}Copy the code
Bad word check chain
package com.example.Chain.support; import com.example.Chain.config.AbstractHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component @Order(3) public class FuckCheckHandler extends AbstractHandler { protected static final Logger logger = LoggerFactory.getLogger(FuckCheckHandler.class); @override protected Boolean doValidate(String param) {if (param. Contains ("fuck")) {logger.info(" {}", param); return false; } return true; }}Copy the code
Responsibility chain service class
package com.example.Chain.service; import com.example.Chain.config.AbstractHandler; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.List; @Component public class CheckChainService { @Resource private List<AbstractHandler> handlerList; private AbstractHandler headHandler; @PostConstruct public void initChain(){ for (int i = 0; i < handlerList.size(); i++) { if (i==0){ headHandler=handlerList.get(0); }else { AbstractHandler preHanlder = handlerList.get(i-1); AbstractHandler curHanlder = handlerList.get(i); preHanlder.setNextHandler(curHanlder); } } } public void checkParam(String param){ headHandler.validate(param); }}Copy the code
The test case
package com.example.Chain.service; import com.example.DesignPattern.DesignPatternApplication; import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; @RunWith(SpringRunner.class) @SpringBootTest(classes = DesignPatternApplication.class) class CheckChainServiceTest { @Resource private CheckChainService checkChainService; @Test void doValidate() { checkChainService.checkParam(""); checkChainService.checkParam("1"); checkChainService.checkParam("fuck u"); }}Copy the code
Implement filtering based on responsibility chain mode
Requirements describe
Dog product: build a feature to filter empty, less than 5, containing bad words for a given set.
You: That’s it?
Dog products: these are the first, you do first, there may be more logic in the future, the above filtering function may be connected to the third party tools, it is hard to say. Different customers have different requirements. You do it first.
You: I’m XXXXX
Code implementation
Define the filter behavior interface
package com.example.Chain2.config;
import java.util.List;
public interface FilterHandler {
List<String> filterWord(List<String> param);
}
Copy the code
Filter the empty
package com.example.Chain2.support; import com.alibaba.fastjson.JSON; import com.example.Chain2.config.FilterHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import java.util.List; @Component public class EmptyFilterHandler implements FilterHandler { protected static final Logger logger = LoggerFactory.getLogger(EmptyFilterHandler.class); @override public List<String> filterWord(List<String> param) {logger.info(" start removing empty words in set, request parameters {}", param); for (int i = param.size() - 1; i >= 0; i--) { if (StringUtils.isEmpty(param.get(i))) { param.remove(i); }} logger.info(" remove element after empty set {}", json.tojsonString (param)); return param; }}Copy the code
Filter less than 5
package com.example.Chain2.support; import com.example.Chain2.config.FilterHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.util.List; @Component public class LengthFilterHandler implements FilterHandler { protected static final Logger logger = LoggerFactory.getLogger(FuckFilterHandler.class); @override public List<String> filterWord(List<String> param) {logger.info(" start filtering words with length less than 5, request parameters {}", param); for (int i = param.size() - 1; i >= 0; i--) { if (param.get(i).length() < 5) { param.remove(i); }} logger.info(" set {} after filtering words less than 5 ", param); return param; }}Copy the code
Filter for bad words
package com.example.Chain2.support; import com.example.Chain2.config.FilterHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.util.List; @Component public class FuckFilterHandler implements FilterHandler { protected static final Logger logger = LoggerFactory.getLogger(FuckFilterHandler.class); @override public List<String> filterWord(List<String> param) {logger.info(" start filtering, request parameters {}", param); for (int i = param.size() - 1; i >= 0; i--) { if (param.get(i).contains("fuck")) { param.remove(i); }} logger.info(" collection of filtered words {}", param); return param; }}Copy the code
Service class
As shown below, load the responsibility chain work class into the service class based on the Spring application context and bean loading post method, so as to complete the chain execution of the responsibility chain more conveniently. If you are not familiar with Spring’s afterPropertiesSet, please refer to my previous article # Hand Spring Chapter 7 – Implementing the convenient bean object initialization and destruction methods
package com.example.Chain2.service; import com.example.Chain2.config.FilterHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.ArrayList; import java.util.List; import java.util.Map; @Component public class FilterWordService implements InitializingBean { protected static final Logger logger = LoggerFactory.getLogger(FilterWordService.class); @Autowired private ApplicationContext applicationContext; private List<FilterHandler> filterHandlerList=new ArrayList<>(); @Override public void afterPropertiesSet() throws Exception { Map<String, FilterHandler> filterHandlerMap = applicationContext.getBeansOfType(FilterHandler.class); filterHandlerMap.forEach((k, v) -> filterHandlerList.add(v)); } public List<String> filterWord(List<String> params) { List<String> result = null; for (FilterHandler filterHandler : filterHandlerList) { result = filterHandler.filterWord(params); If (collectionutils.isempty (result)) {logger.info(" current parameter isEmpty "); return new ArrayList<>(); } } return result; }}Copy the code
The test case
package com.example.Chain2.service; import com.alibaba.fastjson.JSON; import com.example.DesignPattern.DesignPatternApplication; import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest(classes = DesignPatternApplication.class) class FilterWordServiceTest { protected static final Logger logger = LoggerFactory.getLogger(FilterWordServiceTest.class); @Resource private FilterWordService filterWordService; @Test void filterWord() { List<String> words = new ArrayList<>(); words.add("1"); words.add("222"); words.add("fuckfuck"); words.add("hahahaha"); words.add(""); words.add(""); words.add(""); words.add(""); words.add("hello word"); words.add("michael"); List<String> strings = filterWordService.filterWord(words); Logger. info(" whole chain filtered set {}", json.tojsonString (words)); }}Copy the code
The source address
Gitee.com/fugongliude…
reference
Is there a problem with removing elements in a loop of ArrayList?
What is the correct way to delete an element from an ArrayList?
# of actual combat! Say goodbye to pipelining code and talk about common design patterns at work!
During the Spring Festival, I used the chain of responsibility mode to reconstruct the business code
www.cnblogs.com/lm970585581…