Итак, предположим, что вы пишете приложение 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);} |