Итак, предположим, что вы пишете приложение Spring MVC и решаете: «Я хочу создать отдельные инкапсулированные алгоритмы, которые можно поменять местами для выполнения определенного поведения».
Классическим ответом на это было бы «вам нужен шаблон стратегии, мама!». Итак, вот что я сделал, рассмотрим код ниже …
Интерфейс
|
1
2
3
|
public interface MealStrategy { cook(Meat meat);} |
Первая стратегия
|
01
02
03
04
05
06
07
08
09
10
|
@Componentpublic class BurgerStrategy implementsMealStrategy { @Autowired CookerDao cookeryDao; @Override public void cook(Meat meat) { cookeryDao.getBurger(meat); }} |
Следующая стратегия …
|
01
02
03
04
05
06
07
08
09
10
|
@Componentpublic class SausageStrategy implementsMealStrategy { @Autowired CookerDao cookeryDao; @Override public cook(Meat meat) { return cookeryDao.getSausage(meat); }} |
Контекст …
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
@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, например …
|
1
2
3
4
5
6
7
8
|
@Autowiredprivate MealContext mealContext;@RequestMapping(method = RequestMethod.POST)public @ResponseBody Something makeMeal(Meat meat) { mealContext.setMealStrategy(new BurgerStrategy()); mealContext.cookMeal(meat);} |
Обычно это имеет смысл для использования с шаблоном стратегии. Тем не менее, единственная строка, которая заставляет все это рухнуть, это строка в контроллере …
|
1
|
mealContext.setMealStrategy(new BurgerStrategy()) |
Это приведет к тому, что новый экземпляр компонента будет создан вне контекста приложения Spring. Это любопытно, так как вам следует реализовать шаблон в Spring, если вы не можете использовать new для создания нового экземпляра? Задав этот вопрос в StackOverflow, я пришел к выводу, что нужно использовать шаблон внедрения зависимостей (в соответствии со стандартным автоматическим подключением весной) и делать отдельные инъекции стратегий. Во-первых, мне нужно изменить стратегии, чтобы они называли компоненты.
|
1
2
3
4
5
|
@Component("burger")public class BurgerStrategy implements MealStrategy { ... }@Component("sausage")public class SausageStrategy implements SausageStrategy { ... } |
Теперь в контроллере у меня есть отдельные стратегии для использования, поэтому вместо того, чтобы устанавливать стратегию, я просто выбираю соответствующую, которая вводится.
|
01
02
03
04
05
06
07
08
09
10
|
@Resource(name = "burger")MealStrategy burger;@Resource(name = "sausage")MealStrategy sausage;@RequestMapping(method = RequestMethod.POST)public @ResponseBody Something makeMeal(Meat meat) { burger.cookMeal(meat);} |