23种设计模式:10状态模式

允许一个对象在其内部状态改变时改变它的行为,让对象看起来似乎修改了它的类

介绍

状态模式中主要有2个类,分别是Work和State,今天我们利用工作的状态来理解状态模式,比如,我们在工作的时候,根据时间的不同,有以下几种状态。

  • 12点之前:精神百倍
  • 12 - 13点:饿了,午饭:犯困,午休
  • 13 - 17点:下午状态还不错,继续努力
  • 17 - 21点:可能加班,也可能被强制回家
  • 21点之后:不行了,睡着了。
    上面的场景,我们可以看出,我们的工作状态和时间有关(或者被强制回家)。
    所以,我们希望设计一个State类,这个State类代表工作中的时间状态,同时,它可以根据不同的时间状态修改Work的其他状态
    这种当一个对象的内在状态改变时允许改变类的行为,我们称为状态模式。也就是说,Work的行为和State有关。

UML图

状态模式的UML图可能有些复杂,可以结合代码理解

Work类

work类中有3个属性:

  • current:代表当前的状态,这个状态会随hour改变而改变
  • hour:时间,也就是引起变化的原因
  • finish:这个不用太关注,也就另外一个引起变化的原因的例子

writeProgram()方法:

  • 它的作用是,当current发生变化时,通知State接口的子类,让符合要求的State的子类来改变Work的行为
State接口:

下面有6个实现类,实现的方式都差不多,也就不一一介绍了,它的作用是,根据Work的时间状态,从ForenoonState开始判断(途中的虚线箭头),如果找到满足当前时间的状态,就用当前的类,去修改Work的状态;比如途中的NoonState类。
这种回调的修改状态的方式,简化了Work类的逻辑,可以让他专注与自生的业务逻辑,State的子类虽然多了,但是它减少了一系列的if else 的判断语句,也就让逻辑判断更加清晰了
在这里插入图片描述

代码

如果上面的原理明白了,代码也就很简单了,如果还不懂,敲一遍代码也对理解状态模式是一个很好的帮助。

  • Work类
public class Work {
    private State current;//当前状态
    private double hour;//时间
    private boolean finish = false;//结束

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

    public double getHour() {
        return hour;
    }

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

    public boolean getFinish() {
        return finish;
    }

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

    public State getCurrent() {
        return current;
    }

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

    public void writeProgram(){
        current.writeProgram(this);
    }
}
  • State接口
public abstract class State {
    public abstract void writeProgram(Work w);
}

  • 下面是State的子类,逻辑都差不多
public class ForenoonState extends State{
    @Override
    public void writeProgram(Work w) {
        if(w.getHour() < 12){
            System.out.println("当前时间:" + w.getHour() + "点 上午工作,精神百倍");
        } else {
            w.setCurrent(new NoonState());
            w.writeProgram();
        }
    }

}
public class NoonState extends State{
    @Override
    public void writeProgram(Work w) {
        if(w.getHour() < 13){
            System.out.println("当前时间:" + w.getHour() + "点 饿了,午饭:犯困,午休。");
        } else {
            w.setCurrent(new AfternoonState());
            w.writeProgram();
        }
    }
}

public class AfternoonState extends State {
    @Override
    public void writeProgram(Work w) {
        if(w.getHour() < 17){
            System.out.println("当前时间:" + w.getHour() + "点 下午状态还不错,继续努力。");
        } else {
            w.setCurrent(new EveningState());
            w.writeProgram();
        }
    }
}
public class EveningState extends State {
    @Override
    public void writeProgram(Work w) {
        if(w.getFinish()){
            w.setCurrent(new RestState());
            w.writeProgram();
        } else{
            if(w.getHour() < 21){
                System.out.println("当前时间:" +w.getHour()+ "点 加班哦,疲惫之极");
            } else {
                w.setCurrent(new  SleepingState());
                w.writeProgram();
            }
        }
    }
}
public class RestState extends State {
    @Override
    public void writeProgram(Work w) {
        System.out.println("当前时间:" + w.getHour() + "点下班回家了。");
    }
}

public class SleepingState extends State {
    @Override
    public void writeProgram(Work w) {
        System.out.println("当前时间:" + w.getHour() + "点 不行了,睡着了。");
    }
}

  • 使用方式,和打印结果
public class Demo {
    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.setFinish(false);
        emergencyProjects.writeProgram();

        emergencyProjects.setHour(19);
        emergencyProjects.writeProgram();

        emergencyProjects.setHour(22);
        emergencyProjects.writeProgram();

    }
}
当前时间:9.0点 上午工作,精神百倍
当前时间:10.0点 上午工作,精神百倍
当前时间:12.0点 饿了,午饭:犯困,午休。
当前时间:13.0点 下午状态还不错,继续努力。
当前时间:14.0点 下午状态还不错,继续努力。
当前时间:17.0点 加班哦,疲惫之极
当前时间:19.0点 加班哦,疲惫之极
当前时间:22.0点 不行了,睡着了。

总结

  • 状态模式主要是将逻辑判断非常多的情况下,将每个逻辑判断分拆成不同的类,这样有助于后期的代码维护和他人对代码的逻辑的理解。
  • 如果后期业务逻辑有修改,修改或增加单个判断,也不会影响其他的逻辑判断
  • 但如果业务的逻辑判断并不多,也就不必要用状态模式了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值