您当前的位置: 首页 > 

java持续实践

暂无认证

  • 4浏览

    0关注

    746博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

设计模式 状态模式

java持续实践 发布时间:2022-04-03 15:29:03 ,浏览量:4

文章目录
      • 状态模式
      • 状态模式实战.
        • 不使用状态模式的写法
        • 使用状态模式的写法

状态模式

状态模式的情景: 状态模式用于一个行为下的多种状态的变更. 例如活动的审核 , 上线 ,下线状态等.

状态模式实战.

模拟活动的编辑 ,上线 , 审批拒绝, 审批通过等. 并且有些状态的流转是不可行的, 比如编辑中, 到下线.

创建tutorials-22.0-1 模块. 定义状态的枚举

package com.thc.design;

/**
 * 类名称:Status
 * 类描述:  活动状态枚举
 *
 * 创建时间:2022/4/3 10:31
 */
public enum Status {

    // 1创建编辑、2待审核、3审核通过(任务扫描成活动中)、4审核拒绝(可以撤审到编辑状态)、5活动中、6活动关闭、7活动开启(任务扫描成活动中)
    Editing, Check, Pass, Refuse, Doing, Close, Open
}

定义活动的实体类

package com.thc.design;

import lombok.Data;

import java.util.Date;

/**
 * 类名称:ActivityInfo
 * 类描述: 活动信息类
 *
 * 创建时间:2022/4/3 10:30
 */
@Data
public class ActivityInfo {

    // 活动id
    private String activityId;
    // 活动名称
    private String activityName;
    // 活动状态
    private Enum status;
    private Date beginTime;
    private Date endTime;
}

创建活动变化的类

package com.thc.design;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 类名称:ActivityService
 * 类描述:  活动服务业务类
 *
 * 创建时间:2022/4/3 10:34
 */
public class ActivityService {

    private static Map statusMap = 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());
        statusMap.put(activityId, status);
    }

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

    public static Enum queryActivityStatus(String activityId) {
        return statusMap.get(activityId);
    }

    /**
     *  执行状态变更
     * @param activityId
     * @param beforeStatus
     * @param afterStatus
     */
    public static synchronized void execStatus(String activityId, Enum beforeStatus, Enum afterStatus) {
        if (! beforeStatus.equals(statusMap.get(activityId))) return;
        statusMap.put(activityId, afterStatus);
    }
}
不使用状态模式的写法

创建 tutorials-22.0-2模块 创建结果返回对象

package com.thc.design;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 类名称:Result
 * 类描述:执行结果
 *
 * 创建时间:2022/4/3 10:51
 */
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Result {

    // 编码
    private String code;
    // 描述
    private String info;
}

创建ActivityExecStatusController 类, 用于状态的执行.

public class ActivityExecStatusController {

    public Result execStatus(String activityId, Enum beforeStatus, Enum afterStatus) {
        // 编辑变为 提审 关闭
        if (Status.Editing.equals(beforeStatus)) {
            if (Status.Check.equals(afterStatus) || Status.Close.equals(afterStatus)) {
                ActivityService.execStatus(activityId, beforeStatus, afterStatus);
                return new Result("0000", "状态变更成功");
            } else {
                // 只能由状态编辑变为提审或者关闭, 其他状态不允许变更.
                return new Result("0001", "状态变更拒绝");
            }
        }

        // 2. 审核通过 -> 拒绝、关闭、活动中
        if (Status.Pass.equals(beforeStatus)) {
            if (Status.Refuse.equals(afterStatus) || Status.Doing.equals(afterStatus) || Status.Close.equals(afterStatus)) {
                ActivityService.execStatus(activityId, beforeStatus, afterStatus);
                return new Result("0000", "变更状态成功");
            } else {
                return new Result("0001", "变更状态拒绝");
            }
        }

        // 3. 审核拒绝 -> 撤审、关闭
        if (Status.Refuse.equals(beforeStatus)) {
            if (Status.Editing.equals(afterStatus) || Status.Close.equals(afterStatus)) {
                ActivityService.execStatus(activityId, beforeStatus, afterStatus);
                return new Result("0000", "变更状态成功");
            } else {
                return new Result("0001", "变更状态拒绝");
            }
        }

        // 4. 活动中 -> 关闭
        if (Status.Doing.equals(beforeStatus)) {
            if (Status.Close.equals(afterStatus)) {
                ActivityService.execStatus(activityId, beforeStatus, afterStatus);
                return new Result("0000", "变更状态成功");
            } else {
                return new Result("0001", "变更状态拒绝");
            }
        }

        // 5. 活动关闭 -> 开启
        if (Status.Close.equals(beforeStatus)) {
            if (Status.Open.equals(afterStatus)) {
                ActivityService.execStatus(activityId, beforeStatus, afterStatus);
                return new Result("0000", "变更状态成功");
            } else {
                return new Result("0001", "变更状态拒绝");
            }
        }

        // 6. 活动开启 -> 关闭
        if (Status.Open.equals(beforeStatus)) {
            if (Status.Close.equals(afterStatus)) {
                ActivityService.execStatus(activityId, beforeStatus, afterStatus);
                return new Result("0000", "变更状态成功");
            } else {
                return new Result("0001", "变更状态拒绝");
            }
        }

        return new Result("0001", "非可处理的活动状态变更");
    }
}

测试类

public class ApiTest {

    private Logger logger = LoggerFactory.getLogger(ApiTest.class);

    @Test
    public void test() {
        // 初始化数据
        String activityId = "10001";
        ActivityService.init(activityId, Status.Editing);

        ActivityExecStatusController activityExecStatusController = new ActivityExecStatusController();
        // 测试从编辑中,变为审批拒绝
        Result resultRefuse = activityExecStatusController.execStatus(activityId, Status.Editing, Status.Refuse);

        logger.info("测试结果 (编辑中 to 审批拒绝 ):  {}", JSON.toJSONString(resultRefuse));
        Result resultCheck = activityExecStatusController.execStatus(activityId, Status.Editing, Status.Check);
        logger.info("测试结果: 编辑中 to 提交审核 :   {}", JSON.toJSONString(resultCheck));
    }

}

结果如下

13:55:21.513 [main] INFO  com.thc.design.test.ApiTest - 测试结果 (编辑中 to 审批拒绝 ):  {"code":"0001","info":"状态变更拒绝"}
13:55:21.517 [main] INFO  com.thc.design.test.ApiTest - 测试结果: 编辑中 to 提交审核 :   {"code":"0000","info":"状态变更成功"}

使用状态模式的写法

使用状态模式, 进行state的抽象. 每一种状态由一个实体类来维护. 每一种状态到下一个状态, 都是在方法中控制, 无需写if else 最后是StateHandler 对状态的流程统一的处理.

定义tutorials-22.0-3模块 创建状态抽象类 . 里面定义了状态的各个方法.

package com.thc.design;

/**
 * 类名称:State
 * 类描述:    定义状态抽象类
 *
 * 创建时间:2022/4/3 11:11
 */
public abstract class State {

    /**
     *  活动提审
     * @param activityId
     * @param currentStatus
     * @return
     */
    public abstract Result arraignment(String activityId, Enum currentStatus);

    /**
     *  审核通过
     * @param activityId
     * @param currentStatus
     * @return
     */
    public abstract Result checkPass(String activityId, Enum currentStatus);

    /**
     *  审核拒绝
     * @param activityId
     * @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);

}

定义各个状态的抽象类的实现 . 编辑状态实现类 :

package com.thc.design.impl;

import com.thc.design.ActivityService;
import com.thc.design.Result;
import com.thc.design.State;
import com.thc.design.Status;

/**
 * 类名称:EditingState
 * 类描述:  编辑中
 *
 * @author: https://javaweixin6.blog.csdn.net/
 * 创建时间:2022/4/3 11:19
 */
public class EditingState extends State {

    @Override
    public Result arraignment(String activityId, Enum currentStatus) {
        // 活动编辑状态 变为提审状态
        ActivityService.execStatus(activityId, currentStatus, Status.Check);
        return new Result("0000", "活动提审成功");
    }

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

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

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

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

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

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

待审核

/**
 * 类名称:CheckState  待审核
 * 创建时间:2022/4/3 11:23
 */
public class CheckState extends State {

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

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

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

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

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

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

    public Result doing(String activityId, Enum currentStatus) {
        return new Result("0001", "待审核活动不可执行活动中变更");
    }
}

PassState 审核通过

public class PassState extends State {

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

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

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

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

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

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

    public Result doing(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Doing);
        return new Result("0000", "活动变更活动中完成");
    }

}

活动开启

public class OpenState extends State {

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

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

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

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

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

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

    public Result doing(String activityId, Enum currentStatus) {
        ActivityService.execStatus(activityId, currentStatus, Status.Doing);
        return new Result("0000", "活动变更活动中完成");
    }
}

活动关闭

/**
 * 活动状态;活动关闭
 */
public class CloseState extends State {

    public Result arraignment(String activityId, Enum currentStatus) {
        return new Result("0001", "活动关闭不可提审");
    }

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

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

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

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

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

    public Result doing(String activityId, Enum currentStatus) {
        return new Result("0001", "活动关闭不可变更活动中");
    }
}

状态处理服务 对所有的状态进行map

public class StateHandler {

    private Map stateMap = new ConcurrentHashMap();

    // 使用map 封装所有的情况.
    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);
    }
}

对状态服务的统一控制中心, 在构造函数中提供了所有状态和实现的具体关联. 放到map数据结构.

测试类 :

import com.alibaba.fastjson.JSON;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 类名称:ApiTest
 * 创建时间:2022/4/3 11:36
 */
public class ApiTest {

    private Logger logger = LoggerFactory.getLogger(ApiTest.class);

    @Test
    public void test_Editing2Arraignment() {
        String activityId = "100001";
        ActivityService.init(activityId, Status.Editing);

        StateHandler stateHandler = new StateHandler();
        Result result = stateHandler.arraignment(activityId, Status.Editing);
        logger.info("测试结果 (编辑中 to 提审活动 ) : {}", JSON.toJSONString(result));
        logger.info("活动信息 : {}  状态 :{}", JSON.toJSONString(ActivityService.queryActivityInfo(activityId)) ,
                JSON.toJSONString(ActivityService.queryActivityInfo(activityId).getStatus())
                );
    }

    @Test
    public void test_Editing2Open() {
        String activityId = "100001";
        ActivityService.init(activityId, Status.Editing);

        StateHandler stateHandler = new StateHandler();
        Result result = stateHandler.open(activityId, Status.Editing);
        logger.info("测试结果 (编辑中 to 开启活动 ) : {}", JSON.toJSONString(result));
        logger.info("活动信息 : {}  状态 :{}", JSON.toJSONString(ActivityService.queryActivityInfo(activityId)) ,
                JSON.toJSONString(ActivityService.queryActivityInfo(activityId).getStatus())
        );
    }

}

测试了由编辑中到提审活动. 编辑中到开启活动. 结果如下 : 编辑到提审成功. 编辑到开启失败 .

14:51:15.062 [main] INFO  com.thc.design.ApiTest - 测试结果 (编辑中 to 提审活动 ) : {"code":"0000","info":"活动提审成功"}
14:51:15.080 [main] INFO  com.thc.design.ApiTest - 活动信息 : {"activityId":"100001","activityName":"早起学习打卡领奖活动","beginTime":1648968675068,"endTime":1648968675068,"status":"Check"}  状态 :"Check"

14:52:13.181 [main] INFO  com.thc.design.ApiTest - 测试结果 (编辑中 to 开启活动 ) : {"code":"0001","info":"非关闭活动不可开启"}
14:52:13.197 [main] INFO  com.thc.design.ApiTest - 活动信息 : {"activityId":"100001","activityName":"早起学习打卡领奖活动","beginTime":1648968733186,"endTime":1648968733186,"status":"Editing"}  状态 :"Editing"

使用状态模式后, 省去了 if else. 代码结构更加清晰, 但缺点是使用的较多. 每个状态类都会去写所有的状态方法, 需要一定的时间成本.

关注
打赏
1658054974
查看更多评论
立即登录/注册

微信扫码登录

0.1807s