您当前的位置: 首页 > 

顧棟

暂无认证

  • 4浏览

    0关注

    227博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

状态模式(State Pattern)

顧棟 发布时间:2021-06-16 22:16:17 ,浏览量:4

文章目录
  • 状态模式(State Pattern)
    • 状态模式的定义
    • 状态模式的优点
    • 状态模式的缺点
    • 状态模式的结构
    • 状态模式的实现
      • 通用场景
      • 流程审批场景
    • 状态模式的适用场景
    • 注意事项

状态模式(State Pattern) 状态模式的定义

当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。

状态模式的核心是封装,状态的变更引起了行为的变更,从外部看起来就好像这个对象对应的类发生了改变一样。

状态模式的优点
  1. 结构清晰,状态模式将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足"单一职责原则"。
  2. 将状态转换显示化,减少对象间的相互依赖。将不同的状态引入独立的对象中会使得状态转换变得更加明确,且减少对象间的相互依赖。
  3. 状态类职责明确,有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换。
  4. 良好的封装性,这也是状态模式的基本要求,状态变换放置到类的内部来实现,外部的调用不用知道类内部如何实现状态和行为的变换。
状态模式的缺点
  1. 状态模式的使用必然会增加系统的类与对象的个数。
  2. 状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱。
  3. 状态模式对开闭原则的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源码,否则无法切换到新增状态,而且修改某个状态类的行为也需要修改对应类的源码。
状态模式的结构

包含以下主要角色。

  1. 环境类(Context)角色:也称为上下文,它定义了客户端需要的接口,内部维护一个当前状态,并负责具体状态的切换。
  2. 抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为,可以有一个或多个行为。
  3. 具体状态(Concrete State)角色:实现抽象状态所对应的行为,并且在需要的情况下进行状态切换。
状态模式的实现 通用场景
public abstract class State {
    /**
     * 定义一个环境角色,提供子类访问
     */
    protected Context context;

    /**
     * 设置环境角色
     */
    public void setContext(Context context) {
        this.context = context;
    }

    /**
     * 行为1
     */
    public abstract void handle1();

    /**
     * 行为2
     */
    public abstract void handle2();
}
public class Context {
    /**
     * 定义状态
     */
    public final static State STATE1 = new ConcreteState1();
    public final static State STATE2 = new ConcreteState2();
    /**
     * 当前状态
     */
    private State currentState;

    /**
     * 获得当前状态
     */
    public State getCurrentState() {
        return currentState;
    }

    /**
     * 设置当前状态
     */
    public void setCurrentState(State currentState) {
        this.currentState = currentState;
        //切换状态
        this.currentState.setContext(this);
    }

    /**
     * 行为委托
     */
    public void handle1() {
        this.currentState.handle1();
    }

    public void handle2() {
        this.currentState.handle2();
    }
}
public class ConcreteState1 extends State {
    @Override
    public void handle1() {
        System.out.println("State1 is doing things");
    }

    @Override
    public void handle2() {
        // 设置当前状态为stat2
        super.context.setCurrentState(Context.STATE2);
        // 过渡到state2状态,由Context实现
        super.context.handle2();
    }
}
public class ConcreteState2 extends State {
    @Override
    public void handle1() {
        //设置当前状态为state1
        super.context.setCurrentState(Context.STATE1);
        //过渡到state1状态,由Context实现
        super.context.handle1();
    }

    @Override
    public void handle2() {
        System.out.println("State2 is doing things");
    }
}
public static void main(String[] args) {
    //定义环境角色
    Context context = new Context();
    //初始化状态
    context.setCurrentState(new ConcreteState1());
    //行为执行
    context.handle1();
    context.handle2();
}
流程审批场景
public class ActivityInfo {
    /**
     * 活动ID
     */
    private String activityId;
    /**
     * 活动名称
     */
    private String activityName;
    /**
     * 活动状态
     */
    private Enum status;
    /**
     * 开始时间
     */
    private Date beginTime;
    /**
     * 结束时间
     */
    private Date endTime;

    public String getActivityId() {
        return activityId;
    }

    public void setActivityId(String activityId) {
        this.activityId = activityId;
    }

    public String getActivityName() {
        return activityName;
    }

    public void setActivityName(String activityName) {
        this.activityName = activityName;
    }

    public Enum getStatus() {
        return status;
    }

    public void setStatus(Enum status) {
        this.status = status;
    }

    public Date getBeginTime() {
        return beginTime;
    }

    public void setBeginTime(Date beginTime) {
        this.beginTime = beginTime;
    }

    public Date getEndTime() {
        return endTime;
    }

    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }
}
public class ActivityService {

    private static final Map STATUS_MAP = new ConcurrentHashMap();

    public static void init(String activityId, Enum status) {
        // 模拟查询活动信息
        ActivityInfo activityInfo = new ActivityInfo();
        activityInfo.setActivityId(activityId);
        activityInfo.setActivityName("早起学习打卡领奖活动");
        activityInfo.setStatus(status);
        activityInfo.setBeginTime(new Date());
        activityInfo.setEndTime(new Date());
        STATUS_MAP.put(activityId, status);
    }

    /**
     * 查询活动信息
     *
     * @param activityId 活动ID
     * @return 查询结果
     */
    public static ActivityInfo queryActivityInfo(String activityId) {
        // 模拟查询活动信息
        ActivityInfo activityInfo = new ActivityInfo();
        activityInfo.setActivityId(activityId);
        activityInfo.setActivityName("早起学习打卡领奖活动");
        activityInfo.setStatus(STATUS_MAP.get(activityId));
        activityInfo.setBeginTime(new Date());
        activityInfo.setEndTime(new Date());
        return activityInfo;
    }

    /**
     * 查询活动状态
     *
     * @param activityId 活动ID
     * @return 查询结果
     */
    public static Enum queryActivityStatus(String activityId) {
        return STATUS_MAP.get(activityId);
    }

    /**
     * 执行状态变更
     *
     * @param activityId   活动ID
     * @param beforeStatus 变更前状态
     * @param afterStatus  变更后状态 b
     */
    public static synchronized void execStatus(String activityId, Enum beforeStatus, Enum afterStatus) {
        if (!beforeStatus.equals(STATUS_MAP.get(activityId))) {
            return;
        }
        STATUS_MAP.put(activityId, afterStatus);
    }
}
public enum Status {
    // 1创建编辑、2待审核、3审核通过(任务扫描成活动中)、4审核拒绝(可以撤审到编辑状态)、5活动中、6活动关闭、7活动开启(任务扫描成活动中)
    Editing, Check, Pass, Refuse, Doing, Close, Open
}
public class Result {

    public final static String CODE_ERROR = "0001";
    public final static String CODE_OK = "0000";
    /**
     * 编码
     */
    private String code;
    /**
     * 描述
     */
    private String info;

    public Result(String code, String info) {
        this.code = code;
        this.info = info;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }
}
/**
 * 抽象状态类
 */
public abstract class State {

    /**
     * 活动提审
     *
     * @param activityId    活动ID
     * @param currentStatus 当前状态
     * @return 执行结果
     */
    public abstract Result arraignment(String activityId, Enum currentStatus);

    /**
     * 审核通过
     *
     * @param activityId    活动ID
     * @param currentStatus 当前状态
     * @return 执行结果
     */
    public abstract Result checkPass(String activityId, Enum currentStatus);

    /**
     * 审核拒绝
     *
     * @param activityId    活动ID
     * @param currentStatus 当前状态
     * @return 执行结果
     */
    public abstract Result checkRefuse(String activityId, Enum currentStatus);

    /**
     * 撤审撤销
     *
     * @param activityId    活动ID
     * @param currentStatus 当前状态
     * @return 执行结果
     */
    public abstract Result checkRevoke(String activityId, Enum currentStatus);

    /**
     * 活动关闭
     *
     * @param activityId    活动ID
     * @param currentStatus 当前状态
     * @return 执行结果
     */
    public abstract Result close(String activityId, Enum currentStatus);

    /**
     * 活动开启
     *
     * @param activityId    活动ID
     * @param currentStatus 当前状态
     * @return 执行结果
     */
    public abstract Result open(String activityId, Enum currentStatus);

    /**
     * 活动执行
     *
     * @param activityId    活动ID
     * @param currentStatus 当前状态
     * @return 执行结果
     */
    public abstract Result doing(String activityId, Enum currentStatus);
}
/**
 * 活动状态;待审核
 */
public class CheckState extends State {

    @Override
    public Result arraignment(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "待审核状态不可重复提审");
    }

    @Override
    public Result checkPass(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_OK, "活动审核通过完成");
    }

    @Override
    public Result checkRefuse(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Refuse);
        return new Result(Result.CODE_OK, "活动审核拒绝完成");
    }

    @Override
    public Result checkRevoke(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Editing);
        return new Result(Result.CODE_OK, "活动审核撤销回到编辑中");
    }

    @Override
    public Result close(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Close);
        return new Result(Result.CODE_OK, "活动审核关闭完成");
    }

    @Override
    public Result open(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "非关闭活动不可开启");
    }

    @Override
    public Result doing(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "待审核活动不可执行活动中变更");
    }
}
/**
 * 活动状态;活动关闭
 */
public class CloseState extends State {
    @Override
    public Result arraignment(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动关闭不可提审");
    }

    @Override
    public Result checkPass(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动关闭不可审核通过");
    }

    @Override
    public Result checkRefuse(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动关闭不可审核拒绝");
    }

    @Override
    public Result checkRevoke(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动关闭不可撤销审核");
    }

    @Override
    public Result close(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动关闭不可重复关闭");
    }

    @Override
    public Result open(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Open);
        return new Result(Result.CODE_OK, "活动开启完成");
    }

    @Override
    public Result doing(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动关闭不可变更活动中");
    }
}
/**
 * 活动状态;活动中
 */
public class DoingState extends State {

    @Override
    public Result arraignment(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动中不可提审");
    }

    @Override
    public Result checkPass(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动中不可审核通过");
    }

    @Override
    public Result checkRefuse(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动中不可审核拒绝");
    }

    @Override
    public Result checkRevoke(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动中不可撤销审核");
    }

    @Override
    public Result close(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Close);
        return new Result(Result.CODE_OK, "活动关闭成功");
    }

    @Override
    public Result open(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动中不可开启");
    }

    @Override
    public Result doing(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动中不可重复执行");
    }

}
/**
 * 活动状态;编辑中
 */
public class EditingState extends State {

    @Override
    public Result arraignment(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Check);
        return new Result(Result.CODE_OK, "活动提审成功");
    }

    @Override
    public Result checkPass(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "编辑中不可审核通过");
    }

    @Override
    public Result checkRefuse(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "编辑中不可审核拒绝");
    }

    @Override
    public Result checkRevoke(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "编辑中不可撤销审核");
    }

    @Override
    public Result close(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Close);
        return new Result(Result.CODE_OK, "活动关闭成功");
    }

    @Override
    public Result open(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "非关闭活动不可开启");
    }

    @Override
    public Result doing(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "编辑中活动不可执行活动中变更");
    }

}
/**
 * 活动状态;活动开启
 */
public class OpenState extends State {

    @Override
    public Result arraignment(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动开启不可提审");
    }

    @Override
    public Result checkPass(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动开启不可审核通过");
    }

    @Override
    public Result checkRefuse(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动开启不可审核拒绝");
    }

    @Override
    public Result checkRevoke(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动开启不可撤销审核");
    }

    @Override
    public Result close(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Close);
        return new Result(Result.CODE_OK, "活动关闭完成");
    }

    @Override
    public Result open(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "活动不可重复开启");
    }

    @Override
    public Result doing(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Doing);
        return new Result(Result.CODE_OK, "活动变更活动中完成");
    }
}
/**
 * 活动状态;审核通过
 */
public class PassState extends State {

    @Override
    public Result arraignment(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "已审核状态不可重复提审");
    }

    @Override
    public Result checkPass(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "已审核状态不可重复审核");
    }

    @Override
    public Result checkRefuse(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Refuse);
        return new Result(Result.CODE_OK, "活动审核拒绝完成");
    }

    @Override
    public Result checkRevoke(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "审核通过不可撤销(可先拒绝审核)");
    }

    @Override
    public Result close(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Close);
        return new Result(Result.CODE_OK, "活动审核关闭完成");
    }

    @Override
    public Result open(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "非关闭活动不可开启");
    }

    @Override
    public Result doing(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Doing);
        return new Result(Result.CODE_OK, "活动变更活动中完成");
    }
}
/**
 * 活动状态;审核拒绝
 */
public class RefuseState extends State {

    @Override
    public Result arraignment(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "已审核状态不可重复提审");
    }

    @Override
    public Result checkPass(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "已审核状态不可重复审核");
    }

    @Override
    public Result checkRefuse(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Refuse);
        return new Result(Result.CODE_OK, "活动审核拒绝不可重复审核");
    }

    @Override
    public Result checkRevoke(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Editing);
        return new Result(Result.CODE_OK, "撤销审核完成");
    }

    @Override
    public Result close(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Close);
        return new Result(Result.CODE_OK, "活动审核关闭完成");
    }

    @Override
    public Result open(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "非关闭活动不可开启");
    }

    @Override
    public Result doing(String activityId, Enum currentStatus) {
        return new Result(Result.CODE_ERROR, "审核拒绝不可执行活动为进行中");
    }
}
/**
 * 状态处理服务
 */
public class StateHandler {

    private final Map stateMap = new ConcurrentHashMap();

    public StateHandler() {
        // 待审核
        stateMap.put(Status.Check, new CheckState());
        // 已关闭
        stateMap.put(Status.Close, new CloseState());
        // 活动中
        stateMap.put(Status.Doing, new DoingState());
        // 编辑中
        stateMap.put(Status.Editing, new EditingState());
        // 已开启
        stateMap.put(Status.Open, new OpenState());
        // 审核通过
        stateMap.put(Status.Pass, new PassState());
        // 审核拒绝
        stateMap.put(Status.Refuse, new RefuseState());
    }

    public Result arraignment(String activityId, Enum currentStatus) {
        return stateMap.get(currentStatus).arraignment(activityId, currentStatus);
    }

    public Result checkPass(String activityId, Enum currentStatus) {
        return stateMap.get(currentStatus).checkPass(activityId, currentStatus);
    }

    public Result checkRefuse(String activityId, Enum currentStatus) {
        return stateMap.get(currentStatus).checkRefuse(activityId, currentStatus);
    }

    public Result checkRevoke(String activityId, Enum currentStatus) {
        return stateMap.get(currentStatus).checkRevoke(activityId, currentStatus);
    }

    public Result close(String activityId, Enum currentStatus) {
        return stateMap.get(currentStatus).close(activityId, currentStatus);
    }

    public Result open(String activityId, Enum currentStatus) {
        return stateMap.get(currentStatus).open(activityId, currentStatus);
    }

    public Result doing(String activityId, Enum currentStatus) {
        return stateMap.get(currentStatus).doing(activityId, currentStatus);
    }
}
public class Client {

    public static void main(String[] args) {
        testEditing2Arraignment();
        testEditing2Open();
        testRefuse2Doing();
        testRefuse2Revoke();
    }

    private static void testEditing2Arraignment() {
        String activityId = "100001";
        ActivityService.init(activityId, Status.Editing);

        StateHandler stateHandler = new StateHandler();
        Result result = stateHandler.arraignment(activityId, Status.Editing);

        System.out.println("测试结果(编辑中To提审活动):" + JSON.toJSONString(result));
        System.out.println("活动信息:" + JSON.toJSONString(ActivityService.queryActivityInfo(activityId)) + "状态:" + JSON.toJSONString(ActivityService.queryActivityInfo(activityId).getStatus()));
    }

    private static void testEditing2Open() {
        String activityId = "100001";
        ActivityService.init(activityId, Status.Editing);

        StateHandler stateHandler = new StateHandler();
        Result result = stateHandler.open(activityId, Status.Editing);

        System.out.println("测试结果(编辑中To开启活动):" + JSON.toJSONString(result));
        System.out.println("活动信息:" + JSON.toJSONString(ActivityService.queryActivityInfo(activityId)) + "状态:" + JSON.toJSONString(ActivityService.queryActivityInfo(activityId).getStatus()));
    }

    private static void testRefuse2Doing() {
        String activityId = "100001";
        ActivityService.init(activityId, Status.Refuse);

        StateHandler stateHandler = new StateHandler();
        Result result = stateHandler.doing(activityId, Status.Refuse);

        System.out.println("测试结果(拒绝To活动中):" + JSON.toJSONString(result));
        System.out.println("活动信息:" + JSON.toJSONString(ActivityService.queryActivityInfo(activityId)) + "状态:" + JSON.toJSONString(ActivityService.queryActivityInfo(activityId).getStatus()));
    }

    private static void testRefuse2Revoke() {
        String activityId = "100001";
        ActivityService.init(activityId, Status.Refuse);

        StateHandler stateHandler = new StateHandler();
        Result result = stateHandler.checkRevoke(activityId, Status.Refuse);

        System.out.println("测试结果(拒绝To撤审):" + JSON.toJSONString(result));
        System.out.println("活动信息:" + JSON.toJSONString(ActivityService.queryActivityInfo(activityId)) + "状态:" + JSON.toJSONString(ActivityService.queryActivityInfo(activityId).getStatus()));
    }

}
状态模式的适用场景
  • 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时,就可以考虑使用状态模式。
  • 一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时。
注意事项

​ 状态模式适用于当某个对象在它的状态发生改变时,它的行为也随着发生比较大的变化,也就是说在行为受状态约束的情况下可以使用状态模式,而且使用时对象的状态最好不要超过5个。

本文主要参考:

  1. 小傅哥的《重学Java模式》
  2. 《C语言中文网》设计模式的相关内容
  3. 《设计模式之禅》第二版 秦小波
关注
打赏
1663402667
查看更多评论
立即登录/注册

微信扫码登录

0.1878s