Wechat search [Santaizi Aobing] focus on this greedy and lustful programmer.
This article has been included in GitHub github.com/JavaFamily, there are a line of large factory interview complete test sites, information and my series of articles.
preface
We all have the interview experience, but the interview process is similar to a design model, each round of interviewers have their own responsibilities, a candidate’s interview process is like a client’s request process.
Creative design patterns have been shared before in this series of design Patterns articles, so if you are interested, check them out again. Now I’m going to share the behavioral pattern of the three major types of design patterns, and today I’m going to share the chain of responsibility pattern
The outline
define
What is the chain of responsibility? How does it work?
Decouple the sending and receiving of a request so that multiple receiving objects have the opportunity to process the request. These receive objects are strung together in a chain and the request is passed along the chain until one of the receiving objects on the chain can handle it.
This is from Beauty of Design Patterns.
Take another look at the official illustration
- Client: Instantiates a handler’s chain, calling the handleRequest method in the first chain object.
- Handle: Abstract class that the actual processor inherits and then implements the handleRequst method to Handle requests
- ConcreteHandler: A class that inherits the Handler and implements the handleRequst method that handles the business logic classes. Different business modules have different ConcreteHandlers.
This structure is actually relatively simple, but let’s take the interview process to simulate the chain of responsibility!
Code implementation
Suppose you go to a company for an interview. You go to the first interview, the second interview, and the third interview. So what about this mock interview code?
public abstract class Handler {
protected Handler handler;
public void setHandler(Handler handler) {
this.handler = handler;
}
public abstract void handleRequest(Integer times);
}
Copy the code
First we’ll define an abstract Handler Handler and add an abstract Handler method called handleRequest. Then I’ll just write a concrete Handler that inherits the Handler class
public class FirstInterview extends Handler {
@Override
public void handleRequest(Integer times) {
// If it is within the scope of the current Handler, it passes the Handler Handler down
if(times ==1) {// Assume that this is the business logic code for processing
System.out.println("First interview"+times); } handler.handleRequest(times); }}Copy the code
Second, build the first interview Handler, internally implement the handleRequest method, determine whether the current process should handle the business logic, not pass down. Similarly, the codes of the second SecondInterview and FirstInterview are basically the same, so I won’t post them for you and just look at the last one
public class ThreeInterview extends Handler {
@Override
public void handleRequest(Integer times) {
if (times == 3) {
System.out.println("The third interview"+ times + Congratulations on passing the interview, HR will contact you!!); }}public static void main(String[] args) {
Handler first = new FirstInterview();
Handler second = new SecondInterview();
Handler three = new ThreeInterview();
first.setHandler(second);
second.setHandler(three);
// The first interview
first.handleRequest(1);
System.out.println();
// The second interview
first.handleRequest(2);
System.out.println();
// The third interview
first.handleRequest(3); System.out.println(); }}Copy the code
From this result, it can be clearly seen that different handlers handle their own business according to their own responsibilities, which is the responsibility chain.
Application of framework
The chain of responsibility is also reflected in many framework source codes. For example, start learning ServletFilter in SpringMVC
As well as the SpringInterceptor in Spring, it actually uses the idea of chain of responsibility mode to achieve the expansibility of the framework, but also follows the open and closed principle.
DUBBO, as a common RPC framework, also has this idea of responsibility chain.
Let me give you a question to think about, okay?
Once the Dubbo service is exposed, basically any service can be called, but in some special business we need to expose the service, but we do not want to be called by people who do not know the business.
For example: goods inventory modification of dubbo service, we only allow placing orders, shopping cart, adding modified goods and some specified scenarios can be called.
So, what is the solution, interception on the Provider side, only for the specific service allowed to call, otherwise interception is not allowed to execute?
The first method, which is the most common and easiest to think of, is to add the service name APP_NAME as the pass-parameter verification.
Second, implement a DUBBO interceptor that selectively filters RPC calls.
For the above two methods, to give you a detailed description of the second method specific how to achieve, each company will be based on the existing DUBBO source code to do their own specific changes, so the second way is also the need for us to change the line of DUBBO source code.
Start by modifying the ConsumerContextFilter consumer interceptor
Here we’ll use version 2.7.19 of Dubbo as an example. Add APP_NAME to Attachments in the ConsumerContextFilter, and Attachments get the values we padded from them for this RPC call.
GetProperty (“project.name”, “”) to get the service name
I’m not going to expand too much on DUBBO here, but if you have a strong suggestion. So at the end of the design pattern, I will take a detailed analysis of Dubbo, ZAB in ZooKeeper, consistent election algorithm and so on.
Now that the CONSUMER has populated the service name, the Provider also needs to write a ProviderFilter
Here is the basic implementation of how to handle each RPC call interception, and then want the service interception, in the provider inside the filter to specify the DubboProviderFilter, can also be implemented globally.
Note: if this Filter uses the DUBBO package, do not make a mistake.
Examples of real business transformation
If this idea exists in frameworks, how does it apply to business code?
Let me give you an example:
We can display product details in modules, such as head diagram, product information, SKU information, delivery address, installment payment and so on.
So how to assemble to the display of product details?
public abstract class AbstractDataHandler<T> {
// Process modular data
protected abstract T doRequest(String query) throws Exception;
}
Copy the code
We’ll start with an abstract data Handler and then create an ItemInfoHandler and a SkuInfoHandler to inherit the abstract Handler
@Component
public class ItemInfoHandler extends AbstractDataHandler<ItemInfoHandler.ItemInfo> {
@Override
protected ItemInfoHandler.ItemInfo doRequest(String query) {
ItemInfoHandler.ItemInfo info = new ItemInfo();
info.setItemId(123456L);
info.setItemName("Test goods");
return info;
}
@Data
public static class ItemInfo {
private Long itemId;
privateString itemName; }}Copy the code
The same goes for the SkuInfoHandler class
@Component public class SkuInfoHandler extends AbstractDataHandler<SkuInfoHandler.SkuInfo> { @Override protected SkuInfoHandler.SkuInfo doRequest(String query) { SkuInfoHandler.SkuInfo info = new SkuInfoHandler.SkuInfo(); info.setSkuId(78910L); Test SKU info. SetSkuName (" "); return info; } @Data public static class SkuInfo { private Long skuId; private String skuName; }}Copy the code
Finally, there is our test code
@Component
public class DataAggregation {
@Autowired
private SkuInfoHandler skuInfoHandler;
@Autowired
private ItemInfoHandler itemInfoHandler;
public Map convertItemDetail(a) throws Exception {
Map result = new HashMap();
result.put("skuInfoHandler", skuInfoHandler.doRequest("Simulated data request"));
result.put("itemInfoHandler",itemInfoHandler.doRequest("Simulated data request"));
return result;
}
public static void main(String[] args) throws Exception {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
DataAggregation dataAggregation = (DataAggregation) applicationContext.getBean("dataAggregation");
Map map = dataAggregation.convertItemDetail();
System.out.println(JSON.toJSONString(map));
// Print the result data
/ / {" skuInfoHandler ": {" skuId:" 78910, "skuName" : "test SKU"}, "itemInfoHandler" : {" itemId: "123456," itemName ":" test items "}}}}Copy the code
This example is actually slightly modified. Instead of passing the processor down, we build each module’s data in the convertItemDetail method using the actual business logic, and return a Map structure.
Another way to write this is to load each Handler that needs to be handled into a List container and then loop through the doRequest method in each Handler, although this is for other business scenarios.
After reading, we can also find that each Handler can be shared. The code logic of each piece of business is very clear. It feels very comfortable to write such code.
conclusion
Design patterns are not set in stone, and the best patterns are those that fit your current business. Understanding the ideas of our predecessors and assembling our own patterns.
That’s the end of this post, and I’m going to share behavioral design patterns with you.
I’m Aobing, the more you know, the more you don’t know, thank you for your talent: likes, favorites and comments, we’ll see you next time!
This article is constantly updated. You can search “Santaizi Aobing” on wechat and read it for the first time. Reply [Information] There are the interview materials and resume templates for first-line big factories prepared by me.