Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > State query in State Pattern

Reply
Thread Tools

State query in State Pattern

 
 
kk_oop@yahoo.com
Guest
Posts: n/a
 
      08-03-2005
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

 
Reply With Quote
 
 
 
 
Wavemaker
Guest
Posts: n/a
 
      08-03-2005

<(E-Mail Removed)> wrote:

<snip>

> 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?


 
Reply With Quote
 
 
 
 
H. S. Lahman
Guest
Posts: n/a
 
      08-03-2005
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
http://www.velocityreviews.com/forums/(E-Mail Removed)
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
(88OOA-PATH



 
Reply With Quote
 
Ken
Guest
Posts: n/a
 
      08-04-2005

H. S. Lahman wrote:
> Responding to Kk_oop...
>

<snip>


> 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

 
Reply With Quote
 
H. S. Lahman
Guest
Posts: n/a
 
      08-04-2005
Responding to Ken...

>>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.


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 Removed)
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
(88OOA-PATH



 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      08-05-2005
Wavemaker <(E-Mail Removed)> wrote:
> <(E-Mail Removed)> wrote:
>
> <snip>
>
>> 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?


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

 
Reply With Quote
 
Wavemaker
Guest
Posts: n/a
 
      08-05-2005

"Robert Klemme" wrote:
> Wavemaker wrote:
>> <(E-Mail Removed)> wrote:
>>
>> <snip>
>>
>>> 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?

>
> 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.




 
Reply With Quote
 
chuck
Guest
Posts: n/a
 
      08-10-2005
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.

 
Reply With Quote
 
bruno modulix
Guest
Posts: n/a
 
      08-11-2005
(E-Mail Removed) wrote:
> 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 ?


--
bruno desthuilliers
ruby -e "print '(E-Mail Removed)'.split('@').collect{|p|
p.split('.').collect{|w| w.reverse}.join('.')}.join('@')"
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
C++ and design Pattern (Composite design Pattern ) Pallav singh C++ 0 01-22-2012 10:26 PM
C++ and design Pattern (Composite design Pattern ) Pallav singh C++ 0 01-22-2012 10:25 PM
May I have a example of design pattern of "composite", I still feel fuzzy after reading book of Addison-Wesley's"design pattern " jones9413@yahoo.com C++ 1 08-31-2007 04:09 AM
documents related to factory design pattern and Abstract foctory pattern. sunny C++ 1 12-07-2006 04:26 AM
boolean endsWith(String s, Pattern pattern) lepikhin@gmail.com Java 17 11-16-2005 10:31 AM



Advertisments