1 State 模式的定义
不同的状态,不同的行为;或者说,每个状态有着相应的行为。
2 何时使用?
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了它的类。状态模式主要解决的是当控制一个对象状态转接的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的逻辑简化。
State 模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用 If else ifelse 进行状态切换, 如果针对状态的这样判断切换反复出现,我们就要联想到是否可以采取 State 模式了。
不只是根据状态,也有根据属性.如果某个对象的属性不同,对象的行为就不一样,这点在数据库系统中出现频率比较高,我们经常会在一个数据表的尾部,加上 property 属性含义的字段,用以标识记录中一些特殊性质的记录,这种属性的改变(切换)又是随时可能发生的,就有可能要使用 State。
3 是否使用?
在实际使用,类似开关一样的状态切换是很多的,但有时并不是那么明显,取决于你的经验和对系统的理解深度。
4 如何使用?
举例:程序员一天的工作状态,随着时间而变化:
当前时间9.0点 上午工作,精神百倍
当前时间10.0点 上午工作,精神百倍
当前时间12.0点 饿了,午饭;犯困,午休。
当前时间13.0点 下午状态不错,继续努力
当前时间14.0点 下午状态不错,继续努力
当前时间17.0点 加班哦,疲惫至极
当前时间17.0点 加班哦,疲惫至极
当前时间19.0点 加班哦,疲惫至极
当前时间22.0点 不行了,睡着了。
一般做法if else 判断
package xx.study.design.state;
/**
*
方法过长
*/
class IfWork{
private int hour;
private Boolean finish=false;
public int getHour() {
return hour;
}
public void setHour(int hour) {
this.hour = hour;
}
public Boolean getFinish() {
return finish;
}
public void setFinish(Boolean finish) {
this.finish = finish;
}
public void WriteProgram() {
if(hour<12) {
System.out.println("当前时间:"+hour+"点上午工作,精神百倍");
}else if(hour<13) {
System.out.println("当前时间:"+hour+"点饿了,午饭;犯困,午休");
}else if(hour<17) {
System.out.println("当前时间:"+hour+"点下午状态还不错,继续努力");
}else {
if(finish) {
System.out.println("当前时间:"+hour+"点 下班回家了");
}else {
if(hour<21) {
System.out.println("当前时间:"+hour+"点 加班哦,疲惫至极");
}else {
System.out.println("当前时间:"+hour+"点 不行了,睡着了。");
}
}
}
}
}
class Main{
public static void main(String[] args){
IfWork emergencyProjects=new IfWork();
emergencyProjects.setHour(9);
emergencyProjects.WriteProgram();
emergencyProjects.setHour(10);
emergencyProjects.WriteProgram();
emergencyProjects.setHour(12);
emergencyProjects.WriteProgram();
emergencyProjects.setHour(14);
emergencyProjects.WriteProgram();
emergencyProjects.setHour(17);
emergencyProjects.WriteProgram();
emergencyProjects.setFinish(false);
emergencyProjects.WriteProgram();
emergencyProjects.setHour(19);
emergencyProjects.WriteProgram();
emergencyProjects.setHour(22);
emergencyProjects.WriteProgram();
}
}
使用state模式
package xx.study.design.state;
public interface State{
public abstract void WriteProgram(Work w);
}
class Work{
private State current;
private double hour;
private boolean finish=false;
public Work() {
current=new ForenoonState();
}
public State getCurrent() {
return current;
}
public void setCurrent(State current) {
this.current = current;
}
public double getHour() {
return hour;
}
public void setHour(double hour) {
this.hour = hour;
}
public boolean isFinish() {
return finish;
}
public void setFinish(boolean finish) {
this.finish = finish;
}
public void SetState(State s) {
current=s;
}
public void WriteProgram() {
current.WriteProgram(this);
}
}
class ForenoonState implements State{
public void WriteProgram(Work w) {
if(w.getHour()<12) {
System.out.println("当前时间"+w.getHour()+"点 上午工作,精神百倍");
}else {
w.SetState(new NoonState());
w.WriteProgram();
}
}
}
class NoonState implements State{
public void WriteProgram(Work w) {
if(w.getHour()<13) {
System.out.println("当前时间"+w.getHour()+"点 饿了,午饭;犯困,午休。");
}else {
w.SetState(new AfternoonState());
w.WriteProgram();
}
}
}
class AfternoonState implements State{
public void WriteProgram(Work w) {
if(w.getHour()<17) {
System.out.println("当前时间"+w.getHour()+"点 下午状态不错,继续努力");
}else {
w.SetState(new EveningState());
w.WriteProgram();
}
}
}
class EveningState implements State{
public void WriteProgram(Work w) {
if(w.isFinish()) {
w.SetState(new RestState());
w.WriteProgram();
}
else{
if(w.getHour()<21) {
System.out.println("当前时间"+w.getHour()+"点 加班哦,疲惫至极");
}else {
w.SetState(new SleepingState());
w.WriteProgram();
}
}
}
}
class SleepingState implements State{
public void WriteProgram(Work w) {
System.out.println("当前时间"+w.getHour()+"点 不行了,睡着了。");
}
}
class RestState implements State{
public void WriteProgram(Work w) {
System.out.println("当前时间"+w.getHour()+"点 下班回家了");
}
}
class StateDemo{
public static void main(String[] args){
Work emergencyProjects=new Work();
emergencyProjects.setHour(9);
emergencyProjects.WriteProgram();
emergencyProjects.setHour(10);
emergencyProjects.WriteProgram();
emergencyProjects.setHour(12);
emergencyProjects.WriteProgram();
emergencyProjects.setHour(13);
emergencyProjects.WriteProgram();
emergencyProjects.setHour(14);
emergencyProjects.WriteProgram();
emergencyProjects.setHour(17);
emergencyProjects.WriteProgram();
emergencyProjects.setFinish(false);
emergencyProjects.WriteProgram();
emergencyProjects.setHour(19);
emergencyProjects.WriteProgram();
emergencyProjects.setHour(22);
emergencyProjects.WriteProgram();
}
}
5 优缺点
优点:
将与特定状态相关的行为局部化,并且将不同状态的行为分割开来消除庞大的条件分支语句,把各种状态转移逻辑分布到State的子类之间,减少了相互间的依赖。
显式化进行状态转换:为不同的状态引入独立的对象,使得状态的转换变得更加明确。而且状态对象可以保证上下文不会发生内部状态不一致的状况,因为上下文中只有一个变量来记录状态对象,只要为这一个变量赋值就可以了。
缺点:
State模式问题主要是逻辑分散化,状态逻辑分布到了很多的State的子类中,很难看到整个的状态逻辑图,这也带来了代码的维护问题。