【大话设计模式】模式十六:状态模式以及在JDK中的应用

【引入】

        每一天都是起床都是新的一天,上午状态好,中午想睡觉,下午渐恢复,加班是煎熬,这都是一种种状态的变化。由此,我们引出一种设计模式,状态模式

一、状态模式

状态模式(state)当一个对象的内在状态发生变化时线性改变其行为。这个对象看起来像是改变了其类。[DP]

UML类图:

【模式组成】:

  • Context上下文类:维护以个具体状态的实例,这个实例维护当前的状态。
  • State 抽象状态类:定义一个接口来封装与Context的一个特定状态相关的行为。
  • ConcreteState具体状态:每个子类实现一个与Context状态相关的行为。

通用代码:

1、Context:

public class Context {
    State s;
    public void request() {
        s.handle(this);
    }
    public void setS(State s) {
        this.s=s;
    }
}

2、State 抽象状态类:

public abstract class State {
    public abstract void handle(Context c);
}

3、具体状态类 Concrete1、2、3:

public class ConcreteState1 extends State {
    @Override
    public void handle(Context c) {
        System.out.println("目前状态1,正在转向状态2!");
        c.setS(new ConcreteState2());
        c.request();
    }
}
  
public class ConcreteState2 extends State {
    @Override
    public void handle(Context c) {
        System.out.println("目前转移到状态2,正在转向状态3!");
        c.setS(new ConcreteState3());
        c.request();
    }
}
 
public class ConcreteState3 extends State {
    @Override
    public void handle(Context c) {
        System.out.println("已到达状态3,状态转移结束!");
    }
}

 4、测试类

public class Client {
	public static void main(String[] args) {
		Context c=new Context();
		c.setS(new ConcreteState1());
		c.request();
	}
}

 二、应用举例

展示每一天的不同时段的状态

UML类图:

Work类

public class Work {
    private State current;
    private double hour;
    private boolean finish = false;

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

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

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

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

    public State getCurrent() {
        return current;
    }

    public double getHour() {
        return hour;
    }

    public boolean isFinish() {
        return finish;
    }

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

抽象状态类

/**
 * 抽象状态
 */
public abstract class State {
    public abstract void writeProgram(Work work);
}

具体状态类

/**
 * 上午工作状态
 */
public class ForenoonState extends State{
    @Override
    public void writeProgram(Work work) {
        if(work.getHour()<12){
            System.out.println("当前时间:"+work.getHour()+"点 上午工作,精神百倍");
        }
        else {
            work.setCurrent(new NoonState());
            work.writeProgram();
        }
    }
}
/**
 * 中午工作状态
 */
public class NoonState extends State {
    @Override
    public void writeProgram(Work work) {
        if(work.getHour()<13){
            System.out.println("当前时间:"+work.getHour()+"点 饿了,到点该吃饭了");
        }
        else
        {
            work.setCurrent(new AfternoonState());
            work.writeProgram();
        }
    }
}
/**
 * 下午工作状态
 */
public class AfternoonState extends State{
    @Override
    public void writeProgram(Work work) {
        if(work.getHour()<17){
            System.out.println("当前时间:"+work.getHour()+"点 下午状态还不错,继续努力");
        }
        else {
            work.setCurrent(new EveningState());
            work.writeProgram();
        }
    }
}
/**
 * 晚间工作状态
 */
public class EveningState extends State {
    @Override
    public void writeProgram(Work work) {
        if (work.isFinish()) {
            work.setCurrent(new RestState());
            work.writeProgram();
        } else {
            if (work.getHour() < 21) {
                System.out.println("当前时间:" + work.getHour() + "点 还要加班");
            } else {
                work.setCurrent(new SleepingState());
                work.writeProgram();
            }
        }
    }
}
/**
 * 睡眠状态
 */
public class SleepingState extends State{
    @Override
    public void writeProgram(Work work) {
        System.out.println("当前时间:"+work.getHour()+"点 太困了,该睡觉了");
    }
}
/**
 * 下班休息状态
 */
public class RestState extends State{
    @Override
    public void writeProgram(Work work) {
        System.out.println("当前时间:"+work.getHour()+"点 该下班回家了");
    }
}

客户端类

public class Client {
    public static void main(String[] args) {
        Work project=new Work();

        project.setHour(9);
        project.writeProgram();

        project.setHour(12);
        project.writeProgram();

        project.setHour(13);
        project.writeProgram();

        project.setHour(17);
        project.setFinish(false);
        project.writeProgram();

        project.setHour(22);
        project.writeProgram();
    }
}


 三、模式优缺点

1、好处

        将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。简而言之就是,将特定状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个State实现类中,所以通过定义新的子类可以很容易的增加新的状态和转换。这样做的目的就是为了消除庞大的分支语句,大的分支判断通过会使得它们难以修改和扩展。状态模式通过把各种状态转移逻辑分不到State子类之间,来减少相互间的依赖,这样就容易维护和扩展了。

2、使用场景:

        当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式。

3、缺点:

  • 状态模式的使用必然会增加系统类和对象的个数。
  • 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
  • 状态模式对”开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。

注意:在行为受状态约束的时候使用状态模式,而且状态不超过 5 个。


 四、JDK中的应用

1、javax.faces.webapp.FacesServlet

  • 实例方法的执行依赖于实例状态。

 如果文章对你有用,三连支持一下吧!!!

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫蜜柚子茶

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值