State query in State Pattern

Discussion in 'Java' started by kk_oop@yahoo.com, Aug 3, 2005.

  1. Guest

    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
    , Aug 3, 2005
    #1
    1. Advertising

  2. Wavemaker Guest

    <> 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?
    Wavemaker, Aug 3, 2005
    #2
    1. Advertising

  3. H. S. Lahman Guest

    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

    Pathfinder Solutions -- Put MDA to Work
    http://www.pathfindermda.com
    blog: http://pathfinderpeople.blogs.com/hslahman
    (888)OOA-PATH
    H. S. Lahman, Aug 4, 2005
    #3
  4. Ken Guest

    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
    Ken, Aug 4, 2005
    #4
  5. H. S. Lahman Guest

    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

    Pathfinder Solutions -- Put MDA to Work
    http://www.pathfindermda.com
    blog: http://pathfinderpeople.blogs.com/hslahman
    (888)OOA-PATH
    H. S. Lahman, Aug 4, 2005
    #5
  6. Wavemaker <> wrote:
    > <> 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
    Robert Klemme, Aug 5, 2005
    #6
  7. Wavemaker Guest

    "Robert Klemme" wrote:
    > Wavemaker wrote:
    >> <> 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.
    Wavemaker, Aug 5, 2005
    #7
  8. chuck Guest

    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.
    chuck, Aug 10, 2005
    #8
  9. 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 ''.split('@').collect{|p|
    p.split('.').collect{|w| w.reverse}.join('.')}.join('@')"
    bruno modulix, Aug 11, 2005
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    17
    Views:
    1,862
    Chris Uppal
    Nov 16, 2005
  2. sunny
    Replies:
    1
    Views:
    461
    Salt_Peter
    Dec 7, 2006
  3. Pallav singh
    Replies:
    0
    Views:
    353
    Pallav singh
    Jan 22, 2012
  4. Pallav singh
    Replies:
    0
    Views:
    399
    Pallav singh
    Jan 22, 2012
  5. Pallav singh
    Replies:
    1
    Views:
    448
    Peter Remmers
    Jan 22, 2012
Loading...

Share This Page