I will start off by saying I've read through quite a few of the questions that ask about avoiding instanceof but I couldn't really see any that quite fit the bill for what we're seeing. Please let me know if you do see any that address this specific point though!
There's an issue we're facing now where we have a class that is responsible for holding information about actions to be taken at particular times. These times can be of a single action or recurring over some period. There's one field we have (duration of an action) that is only valid for recurring actions. We initially had an Enum for the time type and a separate field for the duration as a part of a single class.
class Action {
long duration;
Enum timeType;
}
Change to:
class Action {
TimeTypeStrategy timeTypeStrategy;
}
class RecurringTimeTypeStrategy extends TimeTypeStrategy {
long duration
}
class SingleTimeTypeStrategy extend TimeTypeStrategy {
}
abstract class TimeTypeStrategy {
}
So with this modified code, we can essentially say that we can only even have one type or the other and that duration can only be a property of the recurring time type. However, this also means that whenever we want to action (or other classes that use action) to handle it based on its recurring time type, it needs to call instanceof on the timeTypeStrategy field to actually retrieve the duration and do whatever scheduling it needs.
One thought was that moving the effort of deciding what it means to be a particular time type can be brought up into the strategy itself. It feels like it should just based off of the name too but that requires changing some of the scheduling code by a fair amount and ends up breaking some of the paradigm that's been developed in just developing these schedules. Maybe that is the solution we need but it feels like it shouldn't be the only one.
As far as design patterns, is there a better method that doesn't lead to an instanceof code smell that allows the caller to decide what to do based on these fields?
Aucun commentaire:
Enregistrer un commentaire