catalogue
1, Before spring, my factory class was implemented in this way .
2. What are the disadvantages?
2, How to use SpringBoot and how to transform it?
1. To add a new handler later, define a Person enumeration first.
3.headMasterHandler implementation class, @ compound needs to be added to let spring manage
4. For the teacherhandler implementation class, @ Compont needs to be added to let spring manage
five PersonHandlerFactory factory
preface
For programmers, the most common estimate of the 23 design patterns is the factory pattern, whether it is a simple factory or an abstract factory. For example, in daily business coding, the handler class is essential for easy maintenance, expansion and management. Generally, an abstract factory is used to uniformly encapsulate the same group of handlers.
1, Before spring, my factory class was implemented in this way .
public class Factory { /** * Object Is the abstract parent interface */ private static final Map<Integer,Object> MAP = new HashMap<>(); /** * Populate MAP with static code blocks */ static { } public static Object getHandle(Integer code){ return MAP.get(code); } }
1. Is this possible?
It must be possible. When using, just call static methods.
2. What are the disadvantages?
- Generally, the specific handler will not be managed by spring. It is possible that our handler needs to use spring managed classes. In this case, you need to use tool classes.
- Most of today's java programmers can be called spring engineers. Since we use spring, it goes against the IOC idea.
- If we need to add a handler, we need to change the factory class. Add a new handler in the static code block.
2, How to use SpringBoot and how to transform it?
Let's first assume that we need to write processors for people in different positions in the school. First extract the top-level interface PersonHandler, and first assume that there are two specific implementation classes
- HeadMasterHandler (principal processor)
- TeacherHandler (teacher processor)
1. To add a new handler later, define a Person enumeration first.
package com.dreamland.springstudy.enums; import lombok.Getter; import lombok.ToString; /** * @author zhangyifeng * @date 2021-10-16 16:52 */ @Getter @ToString public enum PersonEnum { /** * teacher */ TEACHER(10), /** * principal */ HEADMASTER(20), private final int code; PersonEnum(int code) { this.code = code; } }
2.PeronHandler interface
package com.dreamland.springstudy.handler; import com.dreamland.springstudy.enums.PersonEnum; /** * @author zhangyifeng * @date 2021-10-16 16:50 */ public interface PersonHandler { /** * enumeration * @return {@link PersonEnum} */ PersonEnum getPersonEnum(); /** * <pre> * The specific verification logic is implemented by subclasses * Generally, parameters are carried in and defined according to specific business requirements. * This is mainly for spring management, so no parameters are brought in. * </pre> * * @return true or false */ boolean handle(); }
3.headMasterHandler implementation class, @ compound needs to be added to let spring manage
package com.dreamland.springstudy.handler.impl; import com.dreamland.springstudy.enums.PersonEnum; import com.dreamland.springstudy.handler.PersonHandler; import org.springframework.stereotype.Component; /** * @author zhangyifeng * @date 2021-10-16 16:59 */ @Component public class HeadmasterHandler implements PersonHandler { @Override public PersonEnum getPersonEnum() { return PersonEnum.HEADMASTER; } @Override public boolean handle() { System.out.println("The principal calibrator works~~~~"); // Write your own verification logic return true; } }
4. For the teacherhandler implementation class, @ Compont needs to be added to let spring manage
package com.dreamland.springstudy.handler.impl; import com.dreamland.springstudy.enums.PersonEnum; import com.dreamland.springstudy.handler.PersonHandler; import org.springframework.stereotype.Component; /** * @author zhangyifeng * @date 2021-10-16 16:58 */ @Component public class TeacherHandler implements PersonHandler { @Override public PersonEnum getPersonEnum() { return PersonEnum.TEACHER; } @Override public boolean handle() { System.out.println("Teacher calibrator operation~~~~"); // Write your own verification logic return true; } }
five For the PersonHandlerFactory factory, @ Compont needs to be managed by spring
The most important factory classes are as follows. There are two important interfaces to implement and two important methods
- InitializingBean Afterpropertieset() in interface Function: used to initialize alternative static code blocks
- ApplicationContetAware Function of setApplicationContext(ApplicationContext var1) in interface: get ApplicationContext object
The methods in these two interfaces are the key. If you want to know the role of the methods in these two interfaces, you can look at the source code if you are interested. The official explanation is better.
package com.dreamland.springstudy.handler; import lombok.NonNull; import org.springframework.beans.BeansException; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; /** * @author zhangyifeng * @date 2021-10-16 17:03 */ @Component public class PersonHandlerFactory implements InitializingBean, ApplicationContextAware { private static final Map<Integer, Supplier<PersonHandler>> MAP = new HashMap<>(); private ApplicationContext applicationContext; public PersonHandler createHandler(Integer personCode) { Supplier<PersonHandler> p = MAP.get(personCode); if (p != null) { return p.get(); } throw new IllegalArgumentException("No such PersonHandler by code:" + personCode); } @Override public void afterPropertiesSet() throws Exception { applicationContext.getBeansOfType(PersonHandler.class) .values() .forEach(c -> MAP.put(c.getPersonEnum().getCode(), () -> c)); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
6. Test
Check whether it is available. Get the specific handler through the factory. I will write an interface test to make it easier:
package com.dreamland.springstudy.Controller; import com.dreamland.springstudy.handler.PersonHandler; import com.dreamland.springstudy.handler.PersonHandlerFactory; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * @author zhangyifeng * @date 2021-10-16 17:25 */ @RestController @Slf4j public class TestController { @Autowired PersonHandlerFactory personHandlerFactory; @GetMapping("/handler") public void testHandler(@RequestParam("code")Integer code){ log.info("/handler code:{}",code); PersonHandler handler = personHandlerFactory.createHandler(code); handler.handle(); } }
The test results show that different handler s can be obtained from the factory class:
summary
- This is a good extension. For example, we are adding a student handler, which can be used as long as we write two steps.
- Add related definitions in enumeration
- Implement parent interface
- The specific handler is managed by spring. In other aspects, we use srping to manage other classes