java - template - Patrón de estrategia con alubias.
strategy pattern template (2)
Dado que una estrategia concreta se determina muy a menudo en el tiempo de ejecución en función de los parámetros proporcionados, sugeriría algo como sigue.
@Component
public class BurgerStrategy implements MealStrategy { ... }
@Component
public class SausageStrategy implements MealStrategy { ... }
Luego, inyecte todas estas estrategias en un mapa (con el nombre del bean como clave) en el controlador dado y seleccione la estrategia respectiva a petición.
@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);
...
}
Digamos que estoy usando la primavera, tengo las siguientes estrategias ...
Interfaz
public interface MealStrategy {
cook(Meat meat);
}
Primera estrategia
@Component
public class BurgerStrategy implements
MealStrategy {
@Autowired CookerDao cookeryDao;
@Override
public void cook(Meat meat) {
cookeryDao.getBurger(meat);
}
}
Siguiente estrategia ...
@Component
public class SausageStrategy implements
MealStrategy {
@Autowired CookerDao cookeryDao;
@Override
public cook(Meat meat) {
return cookeryDao.getSausage(meat);
}
}
Contexto...
@Component
@Scope("prototype")
public class MealContext {
private MealStrategy mealStrategy;
public void setMealStrategy(MealStrategy strategy) {
this.strategy = strategy;
}
public void cookMeal(Meat meat) {
mealStrategy.cook;
}
}
Ahora digamos que se estaba accediendo a este contexto a través de un controlador mvc, como ...
@Autowired
private MealContext mealContext;
@RequestMapping(method = RequestMethod.POST)
public @ResponseBody Something makeMeal(Meat meat) {
mealContext.setMealStrategy(new BurgerStrategy())
mealContext.cookMeal(meat);
}
¿Debería el contexto ser un componente? Cuando lo hago, aparece un error que dice loadOnStartup y hay un nonBean que puede ser la estrategia, como es de esperar. ¿Todos los beans deben ser componentes como arriba o mis anotaciones son incorrectas?
Mi mayor consulta es si puedes usar un contexto como ese en una aplicación Spring MVC. El problema que tengo con el uso de @Scope (prototipo) también es que las llamadas a cookeryDao en las estrategias devuelven un puntero nulo ya que los Dao no se inyectan.
¿Cómo implementaría el patrón anterior usando el resorte y también sería seguro para los hilos? ¿Es lo que estoy intentando incluso posible?
Yo usaría inyección de dependencia simple.
@Component("burger")
public class BurgerStrategy implements MealStrategy { ... }
@Component("sausage")
public class SausageStrategy implements MealStrategy { ... }
Controlador
Opción A:
@Resource(name = "burger")
MealStrategy burger;
@Resource(name = "sausage")
MealStrategy sausage;
@RequestMapping(method = RequestMethod.POST)
public @ResponseBody Something makeMeal(Meat meat) {
burger.cookMeal(meat);
}
Opción B:
@Autowired
BeanFactory bf;
@RequestMapping(method = RequestMethod.POST)
public @ResponseBody Something makeMeal(Meat meat) {
bf.getBean("burger", MealStrategy.class).cookMeal(meat);
}
Puede elegir crear calificadores JSR-330 en lugar de nombres textuales para detectar errores ortográficos durante el tiempo de compilación.
Ver también:
¿Cómo implementar eficientemente un patrón de estrategia con spring?