State Design Pattern in Java: Before and after
Before
3-speed ceiling fan state machine
// Not good: unwieldy "case" statement
class CeilingFanPullChain {
private int currentState;
public CeilingFanPullChain() {
currentState = 0;
}
public void pull() {
if (currentState == 0) {
currentState = 1;
System.out.println("low speed");
} else if (currentState == 1) {
currentState = 2;
System.out.println("medium speed");
} else if (currentState == 2) {
currentState = 3;
System.out.println("high speed");
} else {
currentState = 0;
System.out.println("turning off");
}
}
}
public class StateDemo {
public static void main(String[] args) {
CeilingFanPullChain chain = new CeilingFanPullChain();
while (true) {
System.out.print("Press ENTER");
getLine();
chain.pull();
}
}
static String getLine() {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line = null;
try {
line = in.readLine();
} catch (IOException ex) {
ex.printStackTrace();
}
return line;
}
}
Output
Press low speed Press medium speed Press high speed Press turning off Press low speed Press medium speed Press high speed Press turning off
After
The CeilingFanPullChain
class is now a wrapper that delegates to its m_current_state reference. Each clause from the "before" case statement is now captured in a State derived class.
For this simple domain, the State pattern is probably over-kill.
interface State {
void pull(CeilingFanPullChain wrapper);
}
class CeilingFanPullChain {
private State currentState;
public CeilingFanPullChain() {
currentState = new Off();
}
public void set_state(State s) {
currentState = s;
}
public void pull() {
currentState.pull(this);
}
}
class Off implements State {
public void pull(CeilingFanPullChain wrapper) {
wrapper.set_state(new Low());
System.out.println("low speed");
}
}
class Low implements State {
public void pull(CeilingFanPullChain wrapper) {
wrapper.set_state(new Medium());
System.out.println("medium speed");
}
}
class Medium implements State {
public void pull(CeilingFanPullChain wrapper) {
wrapper.set_state(new High());
System.out.println("high speed");
}
}
class High implements State {
public void pull(CeilingFanPullChain wrapper) {
wrapper.set_state(new Off());
System.out.println("turning off");
}
}
public class StateDemo {
public static void main(String[] args) {
CeilingFanPullChain chain = new CeilingFanPullChain();
while (true) {
System.out.print("Press ENTER");
getLine();
chain.pull();
}
}
static String getLine() {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line = null;
try {
line = in.readLine();
} catch (IOException ex) {
ex.printStackTrace();
}
return line;
}
}
Output
Press low speed Press medium speed Press high speed Press turning off Press low speed Press medium speed Press high speed Press turning off