Daniel Perez
Daniel Perez

Reputation: 4332

how to design a class where the object state will vary depending on time?

I have a class that has a lifecycle, that is, when time passes, some of its properties vary (I.e.: if you don't drink water for a while then you feel thirsty). Right now what I'm doing is have another class that is constantly calling (while loop called x amounts of time per minute) some methodss on the first one, and there I check against the previous time when the check was done and perform the appropriate actions. However, I'd like to have something cleaner, perhaps some pattern can be used to separate the responsibility of "watching" the object in a more elegant way. I hope it's clear, otherwise i can provide some code

Upvotes: 2

Views: 125

Answers (5)

Daddy
Daddy

Reputation: 9035

What I would do would be to record the system date at object initialization as a property of the object. Then, instead of "watching" the object, have a method inside the object that returns the state by comparing init time to current time.

Won't necessarily resolve your issue with the while loop...but depending on your implementation you may not need a while loop (you can call this object method when it suits you)

EDIT:

for example (abstracted, this is not a language. Substitute methods from your platform)

//MyObject.h
enum {
    NormalObjectState = 0,
    ThirstyObjectState = 1
} ObjectState;

SystemDate _initSystemDate;
-(ObjectState) returnObjectState;

//MyObject.m
- (MyObject) init {
  SystemDate currentTime = GetSystemTime();
  _initSystemTime = currentTime;
  return self;
}

-(ObjectState) returnObjectState {
     SystemDate currentTime = GetSystemTime();
     SystemDateInterval timeInterval = GetTimePassed(_initSystemTime, CurrentTime);
     ObjectState currentState = NormalObjectState;
     if (timeInterval > 60) { //minute passed
         currentState = ThirstyObjectState;
     } 
     return currentState;
}

//in your program code
#import MyObject.h

//...

while (x) {
   ObjectState currentObjectState = [object returnObjectState];
   if (currentObjectState == NormalObjectState) {
      print ("I'm normal");
   } else {
      print ("I'm thirsty");
      [thisClass drinkWater];
   }
}

- (void) drinkWater {
    SystemDate currentTime = GetSystemTime();
    _initSystemTime = currentTime;
}

Upvotes: 0

RalphChapin
RalphChapin

Reputation: 3158

First, the changes definitely need to be handled inside the class; that's just proper OOP. The best way to do that, as mentioned elsewhere, is calculate each value at the time it is requested.

Failing that, you want to run a timer. Ideally you can get one that will run things in some kind of queue (like the Java EventQueue). This keeps everything in one thread. Otherwise you're running multithreaded, which can be somewhat interesting.

Most likely, you can just take the code from the other class and put it in this one. That code has already had to solve these problems anyway.

Where to start the timer can be a trick. If you already have an activate method of some sort you're all set. Otherwise, if you're not multithreaded, just start it in the constructor so the class is ready to go right from the start. (Unless you want to start and stop it several times in a session.) You can do this even running multithreaded, but if you (or anybody else) gets careless or forgetful, other code can get access to the class before it is fully initialized. Or course, without the timer running, a newly constructed instance is not yet fully initialized, so you've got the same problem even if you use an activate method. (I tend to wobble between the two, picking the least-bad solution for each case. Hopefully you're not multithreaded.)

And if a class instance might not be needed for your whole session, you'll need a "dispose" method, and a place to call it from. (If you have an "activate" method, make it a "deactivate" method instead. It might make sense to activate and deactivate on object several times in a sessioin.)

Upvotes: 0

davioooh
davioooh

Reputation: 24706

IMHO having an object that automatically change it's state is NOT a good thing, so I suppose no design pattern exists for this.

As someone suggested to you I think it could be a good idea having in your object a creationDate variable (or something similar) and several methods to check the "needs" of your object. For example:

boolean isThirsty(){
    return (now - lastDrinkDate > MAX_INTERVAL);
}

Upvotes: 0

Hoghweed
Hoghweed

Reputation: 1948

First of all I agree with the concept which @Justin Amberson said, the concept is:

the state of the object will "change" when the state is "requested"

and this would be a way, but this could depend.

Basing only on your question title, the concept above could be enough, but (and this is related to the fact this behavior in which context is done) if this should be an "automatic" behavior, this could be achieved using internally a simple kind of "scheduler" or "timer", which, according to object states, will wait for an amount of time right to the next state occourence; while the "timer" is waiting, if the operation (which blocks the state change) is "requested", eg. "Drink water before 5 minutes from now" the "timer" will be rescheduled to next time occourence for the next state change.

As I said before, this is just "imagination", because basing only on your question title and text, the first concept should be enough and the rest goes out of scope of your question.

Upvotes: 0

SplittyDev
SplittyDev

Reputation: 11

You could use "ticks". Use a tick variable (integer). Increment the tick variable by one every time you call the methods.

For example, if you want the character (or whatever) to feel thursty after 250 ticks, simply modulo-divide the ticks by 250 and check if the result is 0.

Upvotes: 1

Related Questions