How to use abstract factory gracefully in SpringBoot

catalogue

preface  

1, Before spring, my factory class was implemented in this way  .

1. Is this possible?

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.

2.PeronHandler interface

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

  6. Test

summary

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?

  1. 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.
  2. Most of today's java programmers can be called spring engineers. Since we use spring, it goes against the IOC idea.
  3. 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

  1. HeadMasterHandler (principal processor)
  2. 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

  1. InitializingBean   Afterpropertieset() in interface     Function: used to initialize alternative static code blocks
  2. 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

  1. This is a good extension. For example, we are adding a student handler, which can be used as long as we write two steps.
    1. Add related definitions in enumeration
    2. Implement parent interface
  2. The specific handler is managed by spring. In other aspects, we use srping to manage other classes

Tags: Java Spring Boot

Posted on Sun, 24 Oct 2021 15:33:09 -0400 by Kath_php_?