首页 > 代码库 > 状态模式

状态模式

  • 状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

  状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。如果这个状态判断很简单,那就是没有必要用"状态模式"了。

  • UML类图 (网上找的)
    • Context环境类:环境类中维护一个State对象,它是定义了当前的状态
    • State抽象状态类
    • ConcreteState(OpenState和CloseState)具体状态类:每一个类封装了一个状态对应的行为。

技术分享

  • 案例:加班工作一天的状态
 1 package state;
 2 
 3 /**
 4  * Created by huangyichun on 2017/6/30.
 5  */
 6 public class Work {
 7     private int hour;
 8     private boolean finish = false;
 9 
10     public void writeProgram(){
11         if (hour < 12) {
12             System.out.println("当前时间: " + hour + "点 上午工作,精神百倍" );
13         }else if(hour < 13) {
14             System.out.println("当前时间: " + hour + "点 饿了, 午饭:犯困,午休。" );
15         }else if(hour < 17) {
16             System.out.println("当前时间: " + hour + "点 下午状态还不错,继续努力" );
17         }else {
18             if (finish) {
19                 System.out.println("当前时间: " + hour + "点 下班回家了" );
20             }else {
21                 if(hour < 21) {
22                     System.out.println("当前时间: " + hour + "点 加班哦, 疲惫至极" );
23                 }else {
24                     System.out.println("当前时间: " + hour + "点 不行了,睡着了" );
25                 }
26             }
27         }
28     }
29 
30     public boolean isFinish() {
31         return finish;
32     }
33 
34     public void setFinish(boolean finish) {
35         this.finish = finish;
36     }
37 
38     public int getHour() {
39         return hour;
40     }
41 
42     public void setHour(int hour) {
43         this.hour = hour;
44     }
45 }
  • 客户端调用
 1 package state;
 2 
 3 /**
 4  * Created by huangyichun on 2017/6/30.
 5  */
 6 public class Client {
 7     public static void main(String[] args) {
 8 
 9         Work emergencyProject = new Work();
10         emergencyProject.setHour(9);
11         emergencyProject.writeProgram();
12         emergencyProject.setHour(10);
13         emergencyProject.writeProgram();
14         emergencyProject.setHour(12);
15         emergencyProject.writeProgram();
16         emergencyProject.setHour(13);
17         emergencyProject.writeProgram();
18         emergencyProject.setHour(14);
19         emergencyProject.writeProgram();
20         emergencyProject.setHour(17);
21         emergencyProject.writeProgram();
22 
23         emergencyProject.setFinish(false);
24         emergencyProject.setHour(19);
25         emergencyProject.writeProgram();
26         emergencyProject.setHour(22);
27         emergencyProject.writeProgram();
28     }
29 }

采用这种方法实现,产生过多的判断分支,这也意味着它的责任过大,面向对象设计其实就是希望做到代码的责任分解。这个类违背了“单一职责原则”。如果老板规定员工加班最晚到8点,我们则需要修改if语句。

  • 采用状态模式进行重构

  抽象接口

1 package state;
2 
3 /**
4  * Created by huangyichun on 2017/6/30.
5  */
6 public interface State {
7      void writeProgram(Work w);
8 }

  具体实现类

 1 package state;
 2 
 3 /**
 4  * Created by huangyichun on 2017/6/30.
 5  */
 6 public class ForenoonState implements State {
 7     @Override
 8     public void writeProgram(Work w) {
 9         if (w.getHour() < 12) {
10             System.out.println("当前时间: " + w.getHour() + "点 上午工作,精神百倍");
11         }else {
12             w.setCurrent(new NoonState());
13             w.writeProgram();
14         }
15     }
16 }
package state;

/**
 * Created by huangyichun on 2017/6/30.
 */
public class NoonState implements State {
    @Override
    public void writeProgram(Work w) {
        if (w.getHour() < 13) {
            System.out.println("当前时间: " + w.getHour() + "点 饿了, 午饭:犯困, 午休。");
        }else {
            w.setCurrent(new AfternoonState());
            w.writeProgram();
        }
    }
}
package state;

/**
 * Created by huangyichun on 2017/6/30.
 */
public class AfternoonState implements State {
    @Override
    public void writeProgram(Work w) {
        if (w.getHour() < 17) {
            System.out.println("当前时间: " + w.getHour() + "点 下午状态还不错,继续努力");
        }else {
            w.setCurrent(new EveningState());
            w.writeProgram();
        }
    }
}
package state;

/**
 * Created by huangyichun on 2017/6/30.
 */
public class EveningState implements State {
    @Override
    public void writeProgram(Work w) {
        if (w.getHour() < 21) {
            System.out.println("当前时间: " + w.getHour() + "点 加班哦,疲累至极");
        }else {
            w.setCurrent(new SleepingState());
            w.writeProgram();
        }
    }
}
package state;

/**
 * Created by huangyichun on 2017/6/30.
 */
public class SleepingState implements State {
    @Override
    public void writeProgram(Work w) {
            System.out.println("当前时间: " + w.getHour() + "点 不行了,睡着了");
    }
}

 修改后的Work相当于Context类

package state;


/**
 * Created by huangyichun on 2017/6/30.
 */
public class Work {
    private State current;
    private int hour;
    private boolean finish = false;

    public Work() {
        current = new ForenoonState();
    }

    public State getCurrent() {
        return current;
    }

    public void setCurrent(State current) {
        this.current = current;
    }

    public void writeProgram(){
        current.writeProgram(this);
    }

    public boolean isFinish() {
        return finish;
    }

    public void setFinish(boolean finish) {
        this.finish = finish;
    }

    public int getHour() {
        return hour;
    }

    public void setHour(int hour) {
        this.hour = hour;
    }
}

客户端调用代码不变:

package state;

/**
 * Created by huangyichun on 2017/6/30.
 */
public class Client {
    public static void main(String[] args) {

        Work emergencyProject = new Work();
        emergencyProject.setHour(9);
        emergencyProject.writeProgram();
        emergencyProject.setHour(10);
        emergencyProject.writeProgram();
        emergencyProject.setHour(12);
        emergencyProject.writeProgram();
        emergencyProject.setHour(13);
        emergencyProject.writeProgram();
        emergencyProject.setHour(14);
        emergencyProject.writeProgram();
        emergencyProject.setHour(17);
        emergencyProject.writeProgram();

        emergencyProject.setFinish(false);
        emergencyProject.setHour(19);
        emergencyProject.writeProgram();
        emergencyProject.setHour(22);
        emergencyProject.writeProgram();
    }
}

 

 

状态模式