Monday, October 6, 2008

Merging state and command pattern with enum and interface

A post just for the fun :-) I would like to describe how to simply merge the state and command design patterns while using enum and interface in java.

We have for instance a class having a changing state :
public MyClass {
protected IState currentState = new MyState.INIT;
...... // other instance variables
...... // some methods

public void myMethod() {
if(aCondition)
currentState = currentState.nextState();
else
currentState = currentState.previousState();
currentState.execAction();
}
}


We can define the interface IState as follow :

public Interface IState {
public void execAction();
public void undoAction();
public IState nextState();
public IState previousState();
}
A dummy state for the fun :

public enum DummyState implements IState {
NIL ; // only one state

public void execAction(){}; // nothing by default
public void undoAction(){}; // nothing by default
public IEtat nextState(){
return this;
};

public IState previousState(){
return this;
};

}

And then a state MyState :
public enum MyState implements IState {
INIT {
public IState nextState(){ return IN_PROGRESS;}
public IState previousState() { return INIT;}
},
IN_PROGRESS {
public IState nextState(){ return TERMINATED;}
public IState previousState() { return INIT;}
},
SUSPENDED {
public IState nextState(){ return IN_PROGRESS;}
public IState previousState() { return IN_PROGRESS;}
},
TERMINATED {
public void execAction(){
Action anAction = new Action();
anAction.exec();
actionsDone.add(anAction);
};
public IState nextState(){ return ARCHIVED;}
public IState previousState() { return IN_PROGRESS;}

},
ARCHIVED {
public IState nextState(){ return DummyState.NIL;}
public IState previousState() { return TERMINATED;}
}


Vector actionsDone = new Vector();

public void execAction(){}; // nothing by default
public void undoAction(){}; // nothing by default

public IState nextState(){
return this;
};
public IEtat previousState(){
return this;
};
}

And finally the Action :

public Class Action extends Command {
public exec() {
//something to do
}
}

No comments: