2

Wikipedia gave an example of State Pattern:

Define LowerCaseState and MultipleUpperCaseState, both inherite from State.

interface State {
    void writeName(StateContext context, String name);
}

class LowerCaseState implements State {
    @Override
    public void writeName(StateContext context, String name) {
        System.out.println(name.toLowerCase());
        context.setState(new MultipleUpperCaseState());
    }
}

class MultipleUpperCaseState implements State {
    /* Counter local to this state */
    private int count = 0;

    @Override
    public void writeName(StateContext context, String name) {
        System.out.println(name.toUpperCase());
        /* Change state after StateMultipleUpperCase's writeName() gets invoked twice */
        if (++count > 1) {
            context.setState(new LowerCaseState());
        }
    }
}

Then we have a Context class:

class StateContext {
    private State state;

    public StateContext() {
        state = new LowerCaseState();
    }

    /**
     * Set the current state.
     * Normally only called by classes implementing the State interface.
     * @param newState the new state of this context
     */
    void setState(State newState) {
        state = newState;
    }

    public void writeName(String name) {
        state.writeName(this, name);
    }
}

The usage will be:

public class StateDemo {
    public static void main(String[] args) {
        StateContext context = new StateContext();

        context.writeName("Monday");
        context.writeName("Tuesday");
        context.writeName("Wednesday");
        context.writeName("Thursday");
        context.writeName("Friday");
        context.writeName("Saturday");
        context.writeName("Sunday");
    }
}

Noted that both the State interface and StateContext have a writeName() method. If we add more methods like that, say, writePoem(), writeCode(), writeEssay(), etc, we have to add them twice, once in State, and onece in StateContext.

What the writeName() method in StateContext is merely propergate the "write name" request, or event to the States.

Are there any way to eliminate this dupilication? Or is this usually considered acceptable?

  • This is how Composition and interfaces work. I don't see any problems with your code. – Robert Harvey Apr 14 at 16:24
  • 1
    However, note that this is a contrived example; the the StateContext is not required to have the same methods as the state. Generally speaking, StateContext provides operations to be used by client code; these operations depend on the State object internally, and may be realized by calling either some specific operation on the state object, or by some sequence of code that calls several state operations - with the overall effect depending on the current (concrete) state. This depends on how exactly the State abstraction is conceptualized. – Filip Milovanović Apr 14 at 21:33
1

Your delegating the functionality to the state object. Its not duplication as you need to expose the functionality somehow and exposing the state object itself would introduce another layer of coupling.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.