To refactor this...
//THIS IS PROBABLY BAD DESIGN, BUT I HAVE NO IDEA HOW TO IMPROVE.
@Override
public String cook() throws Exception {
switch (recipe.getType()) {
case BURGER:
return cookBurger();
case PIZZA:
return cookPizza();
default:
throw new RecipeTypeNotExistException("Invalid recipe type: " + recipe.getType());
}
}
// Method for cooking Burger
private String cookBurger(){...}
// Method for cooking Pizza
private String cookPizza(){...}
...enhance the business model with a new abstraction that represents cookers...
interface Cooker {
Cooker EMPTY_COOKER = new Cooker() {
boolean cooks(RecipeType type) { return true; }
String cook(Recipe recipe) throws Exception {
throw new RecipeTypeNotExistException("Invalid recipe type: "
+ recipe.getType());
}
};
boolean cooks(RecipeType type);
String cook(Recipe recipe);
}
...with a corresponding implementation for each known cooker...
public class BurgerCooker implements Cooker {
boolean cooks(RecipeType type) { return type == RecipeType.BURGER; }
String cook(Recipe recipe) throws Exception { ... }
}
public class PizzaCooker implements Cooker {
boolean cooks(RecipeType type) { return type == RecipeType.PIZZA; }
String cook(Recipe recipe) throws Exception { ... }
}
...then enhance RecipeCooker class with a constant to keep in memory an instance of each available cooker and an instance variable of type Cooker that must be initialised by the constructor...
public class RecipeCooker {
private static final Cooker[] COOKERS = { new BurgerCooker()
, new PizzaCooker()
};
private final Recipe recipe;
private final Cooker cooker;
private final RecipeRepository recipeRepository;
public RecipeCooker(Recipe recipe
, RecipeRepository recipeRepository) {
this.recipe = recipe;
this.recipeRepository = recipeRepository;
Cooker toBeCooker = Cooker.EMPTY_COOKER;
for ( int i = 0; i < RecipeCooker.COOKERS.length; i++ ) {
if ( RecipeCooker.COOKERS[i].cooks(recipe.getType()) ) {
toBeCooker = RecipeCooker.COOKERS[i];
}
}
this.cooker = toBeCooker;
}
public String cook() throws Exception {
return this.cooker.cook();
}
}
That would be the simples enhancement to keep consistent with the business model that includes a ReceipeCooker model.