toc
#狀态模式
當一個對象的内在狀态改變時允許改變其行為,這個對象看起來像是改變了其類。
在平常開發自己也會遇到好多方法過長,裡面的判斷語句太多,導緻後續修改十分麻煩。今天看到狀态模式的介紹,覺得很受益。下面通過一段代碼錯誤的顯示一遍沒有使用狀态模式的代碼
public class Work {
private int hour;
private boolean finished;
private boolean taskFinished;
public void workProgram() {
if (hour < 12) {
System.out.println("current time: "+new Date() + " working in the morning");
} else if (hour < 13) {
System.out.println("current time: "+new Date() + " have a break!");
} else if (hour < 17) {
System.out.println("current time: "+new Date() + " working in the afternoon");
} else {
if (finished) {
System.out.println("current time: "+new Date() + " after work!");
} else if (hour <12) {
System.out.println("current time: "+new Date() + " very hard!");
}
}
}
}
從上述代碼中看出,當我要修改hour的判斷範圍,或者在各個判斷條件之後新增一些功能,都會使這段方法變得十分長,而且閱讀起來也比較繁瑣。
是以代碼過長了就有壞味道了。在面向對象的設計中也希望做到代碼的責任分解。
複制
當一個對象狀态轉換的條件表達式過于複雜的時候,把狀态的判斷邏輯移到不同的一系列類當中,可以把複雜的判斷邏輯簡單化,這就是狀态模式的主要作用。但并不是所有有判斷的都要使用狀态模式,簡單的判斷邏輯就不需要了。
代碼改良
/**
* 工作類 沒有了判斷語句
*/
public class Work {
private int hour;
private boolean finished;
private boolean taskFinished;
private State state;
private State currentState;
public Work() {
currentState = new ForenoonState();
}
public void workProgram() {
currentState.workProgram(this);
}
public int getHour() {
return hour;
}
public void setHour(int hour) {
this.hour = hour;
}
public boolean isFinished() {
return finished;
}
public void setFinished(boolean finished) {
this.finished = finished;
}
public boolean isTaskFinished() {
return taskFinished;
}
public void setTaskFinished(boolean taskFinished) {
this.taskFinished = taskFinished;
}
public State getState() {
return state;
}
public void setState(State state) {
this.currentState = state;
}
}
/**
* morning
*/
public class ForenoonState extends State {
public void workProgram(Work work) {
if (work.getHour() < 12) {
System.out.println("current time: "+new Date() + " working in the morning");
} else {
work.setState(new NoonState());
}
}
}
/**
* noon
*/
public class NoonState extends State {
public void workProgram(Work work) {
if (work.getHour() < 13) {
System.out.println("current time: "+new Date() + " have a break!");
} else {
work.setState(new AfternoonState());
}
}
}
/**
* afternoon
*/
public class AfternoonState extends State {
public void workProgram(Work work) {
if (work.getHour() < 17) {
System.out.println("current time: "+new Date() + " working in the afternoon");
} else {
//todo .......
}
}
}
/**
* Client
*/
public class Client {
public static void main(String[] args) {
Work work = new Work();
work.setHour(12);
work.workProgram();
work.setHour(13);
work.workProgram();
}
}
複制
image.png
從上術代碼中,在用戶端代碼不需要做任何的修改,程式可以變得非常靈活,當程式還需要添加一個額外的工作狀态時,再添加一個其它狀态類的代碼,也不影響其它狀态類的代碼。