Java设计模式之--状态模式

当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使用状态模式。状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化。状态模式是一种对象行为型模式。
本文代码地址:https://github.com/shelimingming/DesignPattern/tree/master/src/main/java/com/sheliming/strategy

一、请假流程

请假流程.jpg
如图,这是一个简化后的请假流程,员工首先提交请假申请到主管审批、主管审批通过后到hr审批、hr审批通过后就到审批完成状态,主管和hr不同意可以将请假单驳回给员工,员工可以修改后重新提交或者终止请假。

二、一般操作

不使用设计模式,首先我们有一个请假申请的类,每个实例代表一个请假记录。
针对每个操作,当请假单的状态不同会对应不同的操作。

package com.sheliming.state.old;

/**
 * 不使用设计模式
 */
public class LeaveRequest {
    //待提交状态
    private static final int TO_COMMIT = 0;
    //待主管状态
    private static final int TO_MANAGER_CONFIRM = 1;
    //待人力资源审批状态
    private static final int TO_HR_CONFIRM = 2;
    //审批通过状态
    private static final int SUCCESS = 3;
    //终止状态
    private static final int FAILED = 4;

    private int state = TO_COMMIT;

    /**
     * 提交
     */
    public void commit() {
        if (state == TO_COMMIT) {
            System.out.println("提交到主管审核");
            state = TO_MANAGER_CONFIRM;
        }
    }

    /**
     * 终止
     */
    public void stop() {
        if (state == TO_COMMIT) {
            System.out.println("员工终止申请");
            state = FAILED;
        }
    }

    /**
     * 同意
     */
    public void agree() {
        if (state == TO_MANAGER_CONFIRM) {
            System.out.println("主管审批通过,到人力资源审批");
            state = TO_HR_CONFIRM;
        } else if (state == TO_HR_CONFIRM) {
            System.out.println("人力资源审批通过,审批完成");
            state = SUCCESS;
        }
    }

    /**
     * 驳回
     */
    public void disagree() {
        if (state == TO_MANAGER_CONFIRM) {
            System.out.println("主管审批驳回,员工重新提交");
            state = TO_COMMIT;
        } else if (state == TO_HR_CONFIRM) {
            System.out.println("人力资源审批驳回,员工重新提交");
            state = TO_COMMIT;
        }
    }

}

我们来测试一下:

package com.sheliming.state.old;

public class Test {
    public static void main(String[] args) {
        LeaveRequest leaveRequest = new LeaveRequest();
        leaveRequest.commit();
        leaveRequest.disagree();
        leaveRequest.commit();
        leaveRequest.agree();
        leaveRequest.agree();
    }
}

结果:

提交到主管审核
主管审批驳回,员工重新提交
提交到主管审核
主管审批通过,到人力资源审批
人力资源审批通过,审批完成

看起来还是不错的,每个方法去判断当前的状态,来进行不同的操作。
那么问题来了,现在需要每个请假流程都需要经过部门领导的审批,那么我们需要修改这个类的每个if else来加入领导审批的逻辑。这很明显不符合“开闭原则”!!!

三、使用状态模式

先来一下类图:
在这里插入图片描述
首先我们把每个状态抽象出来:

package com.sheliming.state.pattern;

/**
 * 状态的接口,各种状态继承该类
 */
public interface State {
    /**
     * 提交
     */
    void commit();

    /**
     * 终止
     */
    void stop();

    /**
     * 同意
     */
    void agree();

    /**
     * 驳回
     */
    void disagree();
}

然后让所有的状态实现这个接口:(如下只举个例子)

package com.sheliming.state.pattern;

/**
 * 待提交状态
 */
public class ToCommitState implements State {
    private LeaveRequest leaveRequest;

    public ToCommitState(LeaveRequest leaveRequest) {
        this.leaveRequest = leaveRequest;
    }


    @Override
    public void commit() {
        System.out.println("提交到主管审核");
        leaveRequest.setState(leaveRequest.getToManagerConfirmState());
    }

    @Override
    public void stop() {
        System.out.println("员工终止申请");
        leaveRequest.setState(leaveRequest.getFailedState());
    }

    @Override
    public void agree() {

    }

    @Override
    public void disagree() {

    }
}

下面是请假申请类:

package com.sheliming.state.pattern;

/**
 * 使用状态模式的请假申请类
 */
public class LeaveRequest {
    //待提交状态
    private State toCommitState;
    //待主管状态
    private State toManagerConfirmState;
    //待人力资源审批状态
    private State toHrConfirmState;
    //审批通过状态
    private State successState;
    //终止状态
    private State failedState;

    //请假单当前的状态
    private State state;

    public LeaveRequest() {
        toCommitState = new ToCommitState(this);
        toManagerConfirmState = new ToManagerConfirmState(this);
        toHrConfirmState = new ToHrConfirmState(this);
        successState = new SuccessState(this);
        failedState = new FailedState(this);

        state = toCommitState;
    }

    public void commit() {
        state.commit();
    }

    public void stop() {
        state.stop();
    }

    public void agree() {
        state.agree();
    }

    public void disagree() {
        state.disagree();
    }


    //get and set...
}

还是使用之前的测试类,会得到相同的结果。但是如果现在想加一个部门领导审批的流程,我们只需要新写一个待部门领导审批的状态类,再修改和该状态相关的状态类,而其他的类都不需要修改!

四、总结

其实状态模式就是通过内部状态的改变而改变整个类的行为,这个和策略模式的类图一模一样。(不熟悉策略模式的可以看之前的博客https://blog.csdn.net/u011863006/article/details/89223282
那么他们的区别是什么呢?
区别就是他们的“意图”不一样。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值