春豆的策略模式

2022-09-01 10:05:42

假设我正在使用弹簧,我有以下策略...

接口

public interface MealStrategy {
    cook(Meat meat);
}

第一个策略

@Component
public class BurgerStrategy  implements
MealStrategy {
  @Autowired CookerDao cookeryDao;

  @Override
  public void cook(Meat meat) {
      cookeryDao.getBurger(meat);
  }
}

下一步策略...

@Component
public class SausageStrategy  implements
MealStrategy {
  @Autowired CookerDao cookeryDao;

  @Override
  public cook(Meat meat) {
      return cookeryDao.getSausage(meat);
  }
}

上下文。。。

@Component
@Scope("prototype")
public class MealContext {
    private MealStrategy mealStrategy;

    public void setMealStrategy(MealStrategy strategy) {
        this.strategy = strategy;
    }

    public void cookMeal(Meat meat) {
        mealStrategy.cook;
    }
}

现在假设此上下文是通过mvc控制器访问的,例如...

@Autowired
private MealContext mealContext;

@RequestMapping(method = RequestMethod.POST)
public @ResponseBody Something makeMeal(Meat meat) {
    mealContext.setMealStrategy(new BurgerStrategy())
    mealContext.cookMeal(meat);
}

上下文是否应为组件?当我这样做时,我得到一个错误,说loadOnStartup a有一个非UniqueBean的策略,正如你所期望的那样。是所有的bean都需要像上面那样的组件,还是我的注释不正确?

我最大的疑问是,你能在Spring MVC应用程序中使用这样的上下文吗?我使用@Scope(原型)的问题还在于,这意味着策略中的烹饪道调用返回一个空指针,因为道不会被注入。

我如何使用弹簧实现上述模式,同时又是线程安全的?我所尝试的甚至有可能吗?


答案 1

由于具体策略通常是在运行时根据提供的参数左右确定的,因此我建议如下。

@Component
public class BurgerStrategy implements MealStrategy { ... }

@Component
public class SausageStrategy implements MealStrategy { ... }

然后将所有这些策略注入到给定控制器中的映射(以bean名称作为键)中,并根据请求选择相应的策略。

@Autowired
Map<String, MealStrategy> mealStrategies = new HashMap<>;

@RequestMapping(method=RequestMethod.POST)
public @ResponseBody Something makeMeal(@RequestParam(value="mealStrategyId") String mealStrategyId, Meat meat) {
    mealStrategies.get(mealStrategyId).cook(meat);

    ...
}

答案 2

我会使用简单的依赖注入。

@Component("burger")
public class BurgerStrategy implements MealStrategy { ... }

@Component("sausage")
public class SausageStrategy implements MealStrategy { ... }

控制器

备选案文A:

@Resource(name = "burger")
MealStrategy burger;

@Resource(name = "sausage")
MealStrategy sausage;

@RequestMapping(method = RequestMethod.POST)
public @ResponseBody Something makeMeal(Meat meat) {
    burger.cookMeal(meat);
}

备选案文B:

@Autowired
BeanFactory bf;

@RequestMapping(method = RequestMethod.POST)
public @ResponseBody Something makeMeal(Meat meat) {
    bf.getBean("burger", MealStrategy.class).cookMeal(meat);
}

您可以选择创建 JSR-330 限定符而不是文本名称,以在编译时捕获拼写错误。

另请参阅:

如何有效地实施弹簧策略模式?

@Resource与@Autowired


推荐