0

I'm currently working on a java webapp, and I have trouble trying to model the change of states of an object that depends on a start/end date.

As i need to change states in runtime, I'm following the State Pattern for the states, but I have doubts about the proper way to check for the conditions to change states. For example, I have a simple Event class, with an abstract EventState that is empty:

public class Event {
    private Long id;
    private String title;
    private LocalDate startDate;     //mm/dd/yyyy
    private LocalTime startTime;     //hour:minutes
    private LocalDate endDate;       //mm/dd/yyyy
    private LocalTime endTime;       //hour:minutes
    private EventState eventState;
    ...

    //getters, setters, validation,etc

}

And also, many states, some of which depends on the start/endDate. Like starting an event automatically in the startDate, and finishing it in the endDate:

public class StartedState extends EventState {
     //my methods that works for a started Event
}

public class FinishedState extends EventState {
     //my methods that works for a finished Event
}

My current approach is a Scheduler class that checks every Event a minute, and updates the states that way.

Considering that I will have many instances of Event in my application, is there any recommendation or approach to checking for time-based conditions when using the state pattern? Or should I not be using the state pattern for those states in particular?

jaco0646
  • 15,303
  • 7
  • 59
  • 83
lucho
  • 11
  • 2
  • Note: you could also use `LocalDateTime` instead of a separate `LocalDate` and `LocalTime`. – MC Emperor Feb 01 '19 at 12:51
  • 1
    Also note that you should follow the Java Naming Conventions: variable names always start with lowercase, that means `Id` should be `id`. – MC Emperor Feb 01 '19 at 12:53
  • Your Question is unclear and possibly too broad. Your abstract discussion of Scheduler and Event escapes me. You may get a better response with concrete example of what you are trying to achieve. I am voting to close as unclear. – Basil Bourque Feb 01 '19 at 20:05
  • Define your terms. If by “state pattern”, you meant [this](https://en.wikipedia.org/wiki/State_pattern), you should provide such a link in your Question for clarity. – Basil Bourque Feb 01 '19 at 20:07
  • By the way, if you intend your start/stop to be specific moments (points on the timeline), you should be using `Instant` rather than `LocalDate`/`LocalTime`. For example, noon on the 23rd of January in Tokyo Japan is a different moment than in Kolkata India, and more hours different in Paris France. – Basil Bourque Feb 01 '19 at 20:09

1 Answers1

1

My current approach is a Scheduler class that checks every Event a minute, and updates the states that way.

Each object has to have a specific responsibility.
So I don't think that it is the scheduler role to update the states.
The scheduler should at each chosen interval invoke a method such as timeChanged(Instant now) on the event elements to allow them to apply the logic that does the state change if it has.

Considering that I will have many instances of Event in my application, is there any recommendation or approach to checking for time-based conditions when using the state pattern?

Your way is rather nice. Another approach could be creating the timer directly in the event but 1) it costs as you create multiple timers, 2) It gathers more responsibility in Event classes.

Note that if the order of event processing doesn't matter and that it doesn't share state you could parallelize the notification from the scheduler since you have many of them.

With ExecutorService such as :

List<Callable<Void>> timeChangedTasks = ...;
ExecutorService.invokeAll(timeChangedTasks);

Or with a parallel stream :

Instant now = Instant.now();
events.parallelStream()
      .forEach(e-> e.timeChanged(now));
davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • 1
    Excellent Answer. One quibble: The `LocalDateTime` class should not be used to track actual moments. That class purposely lacks any concept of time zone or offset-from-UTC, so by definition it cannot represent a moment. This is noted in the class JavaDoc. Use `ZonedDateTime` instead, or `OffsetDateTime`, or `Instant` for UTC. – Basil Bourque Feb 01 '19 at 19:40
  • @Basil Bourque Thanks for your words and your bright comment. The specific semantic of temporal object is important overall for events handled by an app. I updated with `Instant`. I think that `ZonedDateTime` (with neutral zone or no) is not the best candidate as the temporal object should not be specific to the client time zone. What do you think of it Time Keeper ? By the way, I stumbled cross over https://stackoverflow.com/questions/32437550/whats-the-difference-between-instant-and-localdatetime/32443004 after reading your comment. Really nice :) – davidxxx Feb 02 '19 at 09:47