import java.util.Collection; import java.util.ArrayList; /**************/ /* Interfaces */ /**************/ interface SingleServing { int calories(); boolean hasMeat(); boolean hasEggDairy(); boolean hasPlants(); } interface Eats { public int caloriesConsumed(); } interface EatsPlants extends Eats { public void eat(VeganDish dish, int servings); } interface EatsPlantsEggDairy extends EatsPlants { public void eat(VegetarianDish dish, int servings); } interface EatsMeat extends Eats { public void eat(MeatDish dish, int servings); } interface EatsAnything extends EatsPlantsEggDairy, EatsMeat { } /***************/ /* Ingredients */ /***************/ abstract class Ingredient { private final int grams; protected Ingredient(int grams) { this.grams = grams; } public static <T extends Ingredient> int sumCalories(Collection<T> ingredients) { int sum = 0; for (T ingredient : ingredients) sum += ingredient.calories(); return sum; } public int grams() { return this.grams; } public int calories() { return this.caloriesPerGram() * this.grams; } public abstract int caloriesPerGram(); } /********************/ /* Meat Ingredients */ /********************/ abstract class MeatIngredient extends Ingredient { protected MeatIngredient(int grams) { super(grams); } } class Pork extends MeatIngredient { public Pork(int grams) { super(grams); } public int caloriesPerGram() { return 1; } } class Beef extends MeatIngredient { public Beef(int grams) { super(grams); } public int caloriesPerGram() { return 1; } } class Chicken extends MeatIngredient { public Chicken(int grams) { super(grams); } public int caloriesPerGram() { return 1; } } /*************************/ /* Egg Dairy Ingredients */ /*************************/ abstract class EggDairyIngredient extends Ingredient { protected EggDairyIngredient(int grams) { super(grams); } } class Eggs extends EggDairyIngredient { public Eggs(int grams) { super(grams); } public int caloriesPerGram() { return 1; } } class Cheese extends EggDairyIngredient { public Cheese(int grams) { super(grams); } public int caloriesPerGram() { return 1; } } /*********************/ /* Plant Ingredients */ /*********************/ abstract class PlantIngredient extends Ingredient { protected PlantIngredient(int grams) { super(grams); } } class Nuts extends PlantIngredient { public Nuts(int grams) { super(grams); } public int caloriesPerGram() { return 1; } } class Wheat extends PlantIngredient { public Wheat(int grams) { super(grams); } public int caloriesPerGram() { return 1; } } class Beans extends PlantIngredient { public Beans(int grams) { super(grams); } public int caloriesPerGram() { return 1; } } class Pumpkin extends PlantIngredient { public Pumpkin(int grams) { super(grams); } public int caloriesPerGram() { return 1; } } class Kale extends PlantIngredient { public Kale(int grams) { super(grams); } public int caloriesPerGram() { return 1; } } /**********/ /* Dishes */ /**********/ abstract class Dish implements SingleServing { public boolean isGlutenFree() { return true; } public boolean containsNuts() { return false; } public int plantCalories() { return 0; } public int eggDairyCalories() { return 0; } public int meatCalories() { return 0; } public int calories() { return this.plantCalories() + this.eggDairyCalories() + this.meatCalories(); } } /****************/ /* Vegan Dishes */ /****************/ class VeganDish extends Dish { private Boolean containsGluten = false; private Boolean containsNuts = false; private final Collection<PlantIngredient> plantContents; private final int plantCalories; public VeganDish(Collection<PlantIngredient> plantIngredients) { this.plantContents = plantIngredients; this.plantCalories = Ingredient.sumCalories(plantIngredients); for (PlantIngredient ingredient : plantIngredients) { if (ingredient instanceof Wheat) containsGluten = true; else if (ingredient instanceof Nuts) containsNuts = true; } } public boolean isGlutenFree() { return !this.containsGluten; } public boolean containsNuts() { return this.containsNuts; } public boolean hasMeat() { return false; } public boolean hasEggDairy() { return false; } public boolean hasPlants() { return this.plantContents.size() > 0; } public int plantCalories() { return this.plantCalories; } } /*********************/ /* Vegetarian Dishes */ /*********************/ class VegetarianDish extends VeganDish { private final Collection<EggDairyIngredient> eggDairyContents; private final int eggDairyCalories; public VegetarianDish( Collection<EggDairyIngredient> eggDairyIngredients, Collection<PlantIngredient> plantIngredients ) { super(plantIngredients); this.eggDairyContents = eggDairyIngredients; this.eggDairyCalories = Ingredient.sumCalories(eggDairyIngredients); } public boolean hasEggDairy() { return eggDairyContents.size() > 0; } public int eggDairyCalories() { return eggDairyCalories; } } /***************/ /* Meat Dishes */ /***************/ class MeatDish extends VegetarianDish { private final Collection<MeatIngredient> meatContents; private final int meatCalories; public MeatDish( Collection<MeatIngredient> meatIngredients, Collection<EggDairyIngredient> eggDairyIngredients, Collection<PlantIngredient> plantIngredients ) { super(eggDairyIngredients, plantIngredients); this.meatContents = meatIngredients; this.meatCalories = Ingredient.sumCalories(meatIngredients); } public boolean hasMeat() { return meatContents.size() > 0; } public int meatCalories() { return meatCalories; } } /***********/ /* Recipes */ /***********/ class FriedChickenRecipe { public static Collection<MeatIngredient> meatIngredients() { Collection<MeatIngredient> ingredients = new ArrayList<MeatIngredient>(); ingredients.add(new Chicken(2)); return ingredients; } } class FriedChicken extends MeatDish { public FriedChicken() { super(FriedChickenRecipe.meatIngredients(), new ArrayList<EggDairyIngredient>(), new ArrayList<PlantIngredient>()); } } /**************/ /* Restaurant */ /**************/ class Restaurant { public static Collection<VeganDish> getVeganDishes() { Collection<VeganDish> dishes = new ArrayList<VeganDish>(); return dishes; } public static Collection<MeatDish> getMeatDishes() { Collection<MeatDish> dishes = new ArrayList<MeatDish>(); dishes.add(new FriedChicken()); return dishes; } } /*************/ /* Customers */ /*************/ abstract class Customer implements Eats { private Collection<Dish> dishesConsumed = new ArrayList<Dish>(); protected void consume(Dish dish, int servings) { while (servings-- > 0) dishesConsumed.add(dish); } public int caloriesConsumed() { int totalCal = 0; for (Dish dish : dishesConsumed) totalCal += dish.calories(); return totalCal; } } class VeganCustomer extends Customer implements EatsPlants { public void eat(VeganDish dish, int servings) { consume(dish, servings); } } class VegetarianCustomer extends VeganCustomer { public void eat(VegetarianDish dish, int servings) { consume(dish, servings); } } class IdealCustomer extends VegetarianCustomer implements EatsAnything { public void eat(MeatDish dish, int servings) { consume(dish, servings); } } class AllergicCustomer extends IdealCustomer { private boolean allergicToGluten = false; private boolean allergicToNuts = false; private boolean allergicToDairy = false; public void noteAllergyToGluten() { allergicToGluten = true; } public void noteAllergyToNuts() { allergicToNuts = true; } public void noteAllergyToDairy() { allergicToDairy = true; } protected void consume(Dish dish, int servings) { if (allergicToGluten && !dish.isGlutenFree()) return; if (allergicToNuts && dish.containsNuts()) return; if (allergicToDairy && dish.hasEggDairy()) return; super.consume(dish, servings); } } /********/ /* Chow */ /********/ public class Chow { private static Collection<VeganCustomer> getVeganCustomers() { Collection<VeganCustomer> customers = new ArrayList<VeganCustomer>(); return customers; } private static Collection<EatsAnything> getFamishedCustomers() { Collection<EatsAnything> customers = new ArrayList<EatsAnything>(); customers.add(new IdealCustomer()); return customers; } public static void main(String[] args) { Collection<VeganCustomer> veganCustomers = getVeganCustomers(); Collection<EatsAnything> famishedCustomers = getFamishedCustomers(); Collection<VeganDish> veganDishes = Restaurant.getVeganDishes(); Collection<MeatDish> meatDishes = Restaurant.getMeatDishes(); for (VeganDish dish : veganDishes) { for (VeganCustomer customer : veganCustomers) { customer.eat(dish, 1); } for (EatsAnything customer : famishedCustomers) { customer.eat(dish, 3); } } for (MeatDish dish : meatDishes) { for (VeganCustomer customer : veganCustomers) { customer.eat(dish, 0); } for (EatsAnything customer : famishedCustomers) { customer.eat(dish, 2); System.out.println("eating"); } } for (EatsAnything customer : famishedCustomers) { System.out.println(customer.caloriesConsumed() + " calories consumed"); } } }