State query in State Pattern

K

kk_oop

Hi. I have a question about implementing the state pattern in Java.
I'm implementing the State abstract base class and each specific class
as inner classes of the context class. So I have something like this:

Context: Elevator

State (inner class of Elevator): ElevatorState

Specific States (derived from ElevatorState, inner class of Elevator):
DoorOpenState, DoorClosedState

So Elevator has a currentState attribute of type ElevatorState. This
will be set at any given time to either DoorOpenState or
DoorClosedState.

My question pertains to implementing a way to query the current state.
I see many folks define a series of static final integers to do this,
e.g., public static final int DOOR_OPEN_STATE = 1, etc. Then each
state would have a query that would return the integer value of its
state. Elevator would have a getCurrentState method that delegated to
the state's method.

I think this is unnecessary. I would rather give Elevator a query for
each state, e.g.: isDoorOpen( ) and isDoorClosed( ). I'd implement
isDoorOpen by just saying "return currentState instanceof
DoorOpenState".

I figure I might as well do this, since whoever would want to know the
current state would most likely really be wanting to know if the
Elevator was in a particular state. If I used the int approach, the
client would have to get the state then compare it to one of the
constants. So I figure my alternate approach doesn't add any overhead
beyond the integer approach--it just replaces the integer constants
with the query methods. There is still an if check, but just done with
the query method instead of the integer check.

If you need to add a new state one way, you have to add another
integer. If you add a new state the other way, you add a new query
method.

Taking the "instanceof" also ensures there will be no risk of having
two states accidentally being assigned the same state id.

Any thoughts on this approach?

Thanks!

Ken
 
W

Wavemaker

I would rather give Elevator a query for
each state, e.g.: isDoorOpen( ) and isDoorClosed( ). I'd implement
isDoorOpen by just saying "return currentState instanceof
DoorOpenState".

Hmm, I would just implement this by having a boolean variable called
doorOpen. When a state transition takes place, the action associated
with the transition would set the boolean to the appropriate value. The
boolean would be a member of the context class and the isDoorXXX methods
would only have to reside there (i.e. the inner state classes wouldn't
have to implement the query methods):

public bool isDoorOpen()
{
return doorOpen;
}

public bool isDoorClose()
{
return !doorOpen;
}

So my approach would be to implement any necessary querying with state
variables that are set by the state actions. The context class wouldn't
do anything more that allow the outside world to get their value through
accessors, and it wouldn't do anything with the variables itself.

Does this address the issues you're interested in?
 
H

H. S. Lahman

Responding to Kk_oop...
Hi. I have a question about implementing the state pattern in Java.
I'm implementing the State abstract base class and each specific class
as inner classes of the context class. So I have something like this:

Context: Elevator

State (inner class of Elevator): ElevatorState

Specific States (derived from ElevatorState, inner class of Elevator):
DoorOpenState, DoorClosedState

So Elevator has a currentState attribute of type ElevatorState. This
will be set at any given time to either DoorOpenState or
DoorClosedState.

My question pertains to implementing a way to query the current state.
I see many folks define a series of static final integers to do this,
e.g., public static final int DOOR_OPEN_STATE = 1, etc. Then each
state would have a query that would return the integer value of its
state. Elevator would have a getCurrentState method that delegated to
the state's method.

I think this is unnecessary. I would rather give Elevator a query for
each state, e.g.: isDoorOpen( ) and isDoorClosed( ). I'd implement
isDoorOpen by just saying "return currentState instanceof
DoorOpenState".

The first thing to do is determine how the knowledge about the state of
the door is best expressed in the overall problem solution. One then
defines and interface for Elevator that best suits that overall context.
Then on decides how to implement the knowledge in Elevator.

If there is just one problem context where the state of the door is
needed, capturing the state as a boolean value may be Just Fine.

OTOH, if the problem is such that the state of the door is best captured
in terms of a state variable value, then the first solution
(getDoorState()) is better for the problem context. That would probably
be true if the state must be passed around or saved elsewhere (e.g., a
snapshot of the Elevator state). Whether that state variable is a code
or a boolean doesn't matter unless one is concerned about the future.
Using a code would be better is there is some chance that the state
might have more that two possible states (e.g., OPEN, CLOSED, OPENING,
CLOSING) when requirements change in the future. IOW, it is a more
maintainable solution.

BTW, if you are going to implement a pure boolean solution, then you
don't need separate accessors. isDoorOpen() returns TRUE or FALSE so
the state is unambiguously determined while maintaining the semantics
(i.e., open = TRUE; closed = not open = FALSE) with a single interface
accessor.

Using two accessors for exactly the same semantics is usually not a good
idea. That's because they duplicate the implementation. One may need
to use the accessor to encapsulate requirements changes. For example,
suppose in the future the states could be {OPEN, CLOSED, OPENING,
CLOSING}. You could change the isDoorOpen to be

if ((currentState == OPEN) || (currentState == OPENING))
return TRUE;
else
return FALSE;

Now none of the existing clients need to be touched because you have
provided a mapping to the new states transparently in the accessor.
That's fine so far. However, the problem is that you would have to make
essentially the same change to isDoorClosed as well so that clients
using it got the same mapping. IOW, you need to double edit the change
if you use two accessors for the same semantics.
I figure I might as well do this, since whoever would want to know the
current state would most likely really be wanting to know if the
Elevator was in a particular state. If I used the int approach, the
client would have to get the state then compare it to one of the
constants. So I figure my alternate approach doesn't add any overhead
beyond the integer approach--it just replaces the integer constants
with the query methods. There is still an if check, but just done with
the query method instead of the integer check.

And what if the client is just collecting a snapshot sample of the
Elevator state {door state, floor, passenger count, etc.) for some sort
of statistical analysis program? Now you need to save the state of the
door as an attribute value in some other object. The boolean will still
work but you run the risk of getting the TRUE/FALSE semantics inverted
somewhere between Elevator and whoever eventually processes the state.
If you use an enumerated numeric code there is no chance of the final
context misinterpreting the state no matter how many copies, etc. there
are (so long as the final context uses the same definition header).


*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
(e-mail address removed)
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
(888)OOA-PATH
 
K

Ken

H. S. Lahman said:
Responding to Kk_oop...
If you use an enumerated numeric code there is no chance of the final
context misinterpreting the state no matter how many copies, etc. there
are (so long as the final context uses the same definition header).

Hmmm. How about having the state object define an abstract
getStateName method that returns a String. The string can be defined
in the specific state implementation of getStateName. Then anyone who
wants to know what state they have can just compare getStateName
against a String literal. This would preclude me from having to define
the set of int constants, but still give me a known value associated
with the state.

Any thoughts on how that compares to the int constant approach? Note
that I actually will have about 6 states. I was just using the
opened/closed as a simple example.

Thanks again,

Ken
 
H

H. S. Lahman

Responding to Ken...
Hmmm. How about having the state object define an abstract
getStateName method that returns a String. The string can be defined
in the specific state implementation of getStateName. Then anyone who
wants to know what state they have can just compare getStateName
against a String literal. This would preclude me from having to define
the set of int constants, but still give me a known value associated
with the state.

Any thoughts on how that compares to the int constant approach? Note
that I actually will have about 6 states. I was just using the
opened/closed as a simple example.

The main drawback is performance; comparing strings at runtime is a
downer. If you employ things like enumeration, #define, or int const,
then the compiler does the string comparison once. [I don't do Java so
I have no clue how the Java VM deals with enumeration; hopefully it has
some cute way to avoid the string compare. If it doesn't, then int
const will be significantly faster.]

Another potential drawback is maintainability. You should define the
string literal(s) in one place so that you don't have to double edit
multiple contexts if there are changes. If you do that, then there
really is very little conceptual difference between the string literal
and an enumeration, #define, or int const definition. At that point
standardization of the technique for defining constants comes into play.
Enumeration or int const is a de facto standard technique so deviating
from it invites foot-shooting during maintenance.


*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
(e-mail address removed)
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
(888)OOA-PATH
 
R

Robert Klemme

Wavemaker said:
Hmm, I would just implement this by having a boolean variable called
doorOpen. When a state transition takes place, the action associated
with the transition would set the boolean to the appropriate value.
The boolean would be a member of the context class and the isDoorXXX
methods would only have to reside there (i.e. the inner state classes
wouldn't have to implement the query methods):

public bool isDoorOpen()
{
return doorOpen;
}

public bool isDoorClose()
{
return !doorOpen;
}

So my approach would be to implement any necessary querying with state
variables that are set by the state actions. The context class
wouldn't do anything more that allow the outside world to get their
value through accessors, and it wouldn't do anything with the
variables itself.
Does this address the issues you're interested in?

Why using a boolean var when the value depends on the state (class)? A
simple "public boolean isOpen() { return true;}" in the state class is
sufficient. If you need it accessible as method in the context class just
create a delegate method.

Kind regards

robert
 
W

Wavemaker

Robert Klemme said:
Why using a boolean var when the value depends on the state (class)?
A simple "public boolean isOpen() { return true;}" in the state class
is sufficient. If you need it accessible as method in the context
class just create a delegate method.

Good point. The boolean variable just adds an extra bit of complexity
that isn't needed.
 
C

chuck

For debugging/logging purposes I 'd give my state classes a toString()
method and a getter on the context to access the state object - but
only if nececsary.

I think the real question here is do you want to expose the state of
the context? Perhaps it is better to allow the context/state object
itself to make decisions about behavior that varies with state?
Exposing the state suggests that there might be some code that has
if/else if/.../else or switch/case statements doing different things
based on the state. Don't fall into this trap... it is the reason you
use the state pattern to begin with. Use the polymorphism provided by
the state hierarcy instead.
 
B

bruno modulix

Hi. I have a question about implementing the state pattern in Java.
I'm implementing the State abstract base class and each specific class
as inner classes of the context class. So I have something like this:

Context: Elevator

State (inner class of Elevator): ElevatorState

Specific States (derived from ElevatorState, inner class of Elevator):
DoorOpenState, DoorClosedState

So Elevator has a currentState attribute of type ElevatorState. This
will be set at any given time to either DoorOpenState or
DoorClosedState.

My question pertains to implementing a way to query the current state.

<meta>
fu2 c.object, nothing specific to Java here...
</meta>

<warning context="oo dogmatic purist ahead">

What's the point of having states if you need to 'query the current
state' ? What's the point of OO and polymorphism if you end up testing
state in a big switch ?

Tell don't ask.

Whatever object you think needs to query your elevator for it's state
should just send the appropriate message to elevator, which delegate to
state, which takes appropriate action. This is what the State pattern is
all about, isn't it ?

</warning>

Ok, I guess this is a bit extrem, and you surely have valid reasons for
what you want to do. But could you tell us more about those reasons ?
What are the use cases ? Who needs to know this, and why ?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,053
Latest member
BrodieSola

Latest Threads

Top