使用 spring 的工厂模式

factory pattern using spring

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

这是一个粗略的例子:

@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;
    }
}

您可以自动装配相同类型的 beans 列表。因此,假设您将 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();
    }

}

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