Итак, предположим, что вы пишете приложение Spring MVC и решаете: «Я хочу создать отдельные инкапсулированные алгоритмы, которые можно поменять местами для выполнения определенного поведения».
Классическим ответом на это было бы «вам нужен шаблон стратегии, мама!». Итак, вот что я сделал, рассмотрим код ниже …
Интерфейс
1
2
3
|
public interface MealStrategy { cook(Meat meat); } |
Первая стратегия
01
02
03
04
05
06
07
08
09
10
|
@Component public class BurgerStrategy implements MealStrategy { @Autowired CookerDao cookeryDao; @Override public void cook(Meat meat) { cookeryDao.getBurger(meat); } } |
Следующая стратегия …
01
02
03
04
05
06
07
08
09
10
|
@Component public class SausageStrategy implements MealStrategy { @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
|
@Autowired private 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); } |