I'm refactoring a specific model from a meal planner software. You schedule out 3 meals for each day of the week, with recipes that fit within the daily nutritional requirements. Some recipes are also selectable as leftovers for other days of the week.
A single serving recipe has a DayItemType::UNIQUE, and when selected as leftover a new DayItem is created with DayItemType::LEFTOVER_PARENT.
These are the DayItemType enum - SKIPPED, UNIQUE, LEFTOVER_PARENT, LEFTOVER, IDENTICAL_OF
The DayItem is currently modeled as such:
public function __construct(
protected DayItemId $id,
protected DayItemType $type,
protected DayItemCategory $category,
protected array $value = [],
protected int $servings = 1
){}
The problem is that I need to satisfy a new business constraint that requires the following:
A DayItem with a DayItemType::UNIQUE does NOT required storage instructions.
A DayItem with a DayItemType::LEFTOVER_PARENT DOES required storage instructions.
e.g "Makes a total of 3 servings. Eat 1 serving today and save 1 serving for day 4 and day 5".
At the moment, the DayItem acts as a base class where the $value property holds the recipe data (title, img, instructions, ingredients, etc) but now I need to add the storage instructions only when the DayItemType equals LEFTOVER_PARENT and I know it should be a responsibility that's directly involved with the DayItemType class, and not the DayItem class itself.
I'm not sure how to satisfy that constraint, there's a few options I can think of but none that's clear enough for me to understand I should implement it as such.
I could create a new property in the DayItem named "storage" but that means all DayItems would always have an initial empty storage value, even ones that don't need it. This is a related question I'm basing things off of, the CustomerDiscount route sounds much more reasonable than creating concrete classes.
Abstract Factory pattern? I could create an abstract class of the DayItem, then create DayItemUnique, DayItemLeftoverParent, DayItemLeftover, DayItemEtc.
I also thought of moving the value property from the DayItem to the DayItemType and also creating an additional data property in the DayItemType (type, value, data) for additional storage information and such but that's not OOP.