使用弹簧的工厂模式

1 spring dependency-injection factory-method

如何根据 SpringBoot 上的请求参数选择服务实现?我可以通过手动实例化服务来做到这一点,但这并没有利用 Spring Injection 功能。我也可以分别自动装配这两个服务,但我想如果我有更多的实现会污染类。

这是一个粗略的例子:

@RestController
class RestControllerTest {

    @Autowired
    PizzaService pizzaService;

    public void bakePizza(@RequestParam("type") String type,@RequestParam("extra") String extra) {

        if (type.equals("cheese")) {
            //set pizzaService Cheese Implementation
            pizzaService = new CheezePizza();
        } else {
            //set PizzaService vegetable Impleentation;
            pizzaService = new VegetablePizza();
        }
        pizzaService.prepareIngredients(extra);
        pizzaService.bakePizza();
    }

}

public abstract class PizzaService {

    String ingredients;

    public abstract void prepareIngredients(String exraIngredient);

    public void bakePizza() {
        System.out.println("baking pizza with " + ingredients);
    }
}

class CheezePizza extends PizzaService {

    @Override
    public void prepareIngredients(String exraIngredient) {
        ingredients = "Cheese " + exraIngredient;
    }
}

class VegetablePizza extends PizzaService {
    @Override
    public void prepareIngredients(String exraIngredient) {
        ingredients = "Vegetable " + exraIngredient;
    }
}
Run Code Online (Sandbox Code Playgroud)

Jak*_*icz 7

您可以自动装配相同类型的 bean 列表。因此,假设您添加getType()到您的PizzaService每个类型并将其注册为 spring bean。

public abstract class PizzaService {
    abstract String getType();
}

@Component
class CheezePizza extends PizzaService {
    @Override
    public String getType() {
        return "cheese";
    }
}

@Component
class VegetablePizza extends PizzaService {
    @Override
    public String getType() {
        return "vegetable";
    }
}


@RestController
class RestControllerTest {

    private final Map<String, PizzaService> pizzaServices;

    public RestControllerTest(List<PizzaService> services) {
        pizzaServices = services.stream().collect(Collectors.toMap(PizzaService::getType, Function.identity()));
    }

    public void bakePizza(@RequestParam("type") String type, @RequestParam("extra") String extra) {
        PizzaService pizzaService = pizzaServices.get(type); // remember of handling missing type
        pizzaService.prepareIngredients(extra);
        pizzaService.bakePizza();
    }

}
Run Code Online (Sandbox Code Playgroud)

另一种方法是按约定使用 ie 命名您的 bean cheesePizzavegetablePizza然后使用ApplicationContext#getBean(type + "Pizza")但我更喜欢第一种方法,因为它不那么神奇。