1、定义
(State)当一个对象的内在状态改变时允许变其行为,这个对象看起来像是改变了其类。
2、使用场景
9点 上午工作 ,精神百倍
10点 上午工作,精神百倍
12点 饿了,午饭,犯困,午休
13点 下午状态还不错,继续努力
14点 下午状态还不错,继续努力
17点 加班额,疲劳至极
19点 加班额,疲劳至极
22点 不行了,睡着了
具体案例演变过程可参考书上
3、代码结构UML图
工作:维护一个ConcreteState子类的实例,这个实例定义当前状态;
状态:抽象状态 类,定义一个接口以封装与Context的一个特定状态相关的行为;
上午、中午、下午、傍晚、下班、睡眠工作状态:具体状态类,每一个子类实现一个与Context的一个状态相关的行为。
4、类的实现
(1)、State(抽象状态)
public abstract class State {
public abstract void writeProgram(Work w);
}
(2)、ForenoonState(上午工作状态类)
public class ForenoonState extends State{
@Override
public void writeProgram(Work w) {
if(w.getHour()<12){
System.out.println("当前时间:"+w.getHour()+"点 上午工作,精神百倍");
}else{
w.setState(new NoonState());
w.writeProgram();
}
}
}
(3)、NoonState(中午工作状态类)
public class NoonState extends State{
@Override
public void writeProgram(Work w) {
if(w.getHour()<13){
System.out.println("当前时间:"+w.getHour()+"点 饿了,午饭;犯困,午休。");
}else{
w.setState(new AfternoonState());
w.writeProgram();
}
}
}
(4)、AfternoonState (下午工作状态类)
public class AfternoonState extends State {
@Override
public void writeProgram(Work w) {
if(w.getHour()<17){
System.out.println("当前时间:"+w.getHour()+"点 下午状态还不错,继续努力。");
}else{
w.setState(new EveningState());
w.writeProgram();
}
}
}
(5)、EveningState (傍晚工作状态类)
public class EveningState extends State {
@Override
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();
}
}
}
}
(6)、SleepingState (睡眠工作状态类)
public class SleepingState extends State {
@Override
public void writeProgram(Work w) {
System.out.println("当前时间:"+w.getHour()+"点 不行了,睡着了。");
}
}
(7)、RestState(下班休息状态类)
public class RestState extends State {
@Override
public void writeProgram(Work w) {
System.out.println("当前时间:"+w.getHour()+"点 下班回家了。");
}
}
5、客户端调用
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();
}
输出:
6、总结
状态模式的好处是将与特定状态相关的行为局部化,并将不同状态的行为分割开来。
将特定状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换。
状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。例如活字印刷术把版面改成了一个又一个的活字,此时就容易维护和扩展了。
当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
另外如果业务需求某项业务又多个状态,通常都是一些枚举常量,状态的变化都是依靠大量的多分支判断语句来实现,此时应该考虑将每一个业务状态定义为一个State的子类。这样这些对象就可以不依赖于其他对象而独立变化了,某一天客户需要更改需求,增加或减少业务状态或改变状态流程,对你来说都时不困难的事。
参考:《大话设计模式》