您当前的位置: 首页 > 

java持续实践

暂无认证

  • 2浏览

    0关注

    746博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

设计模式 责任链模式

java持续实践 发布时间:2022-03-28 22:33:58 ,浏览量:2

文章目录
      • 责任链模式场景
      • 责任链模式实战
        • 不使用责任链模式的写法
        • 使用责任链模式的写法

责任链模式场景

用于解决一组服务中的先后执行处理关系, 例如出差补贴, 不超过100的组内领导审批, 超过100不超过200的,先组内领导审批接着部门领导审批, 超过200不超过300 的, 从组内领导 到部门领导, 再到公司领导挨个审批.

责任链模式实战

模拟上线的三级 二级 一级 审批. 平时用三级审批. 临近促销二级审批. 618, 双十一期间需要一级审批.

不使用责任链模式的写法

创建模块tutorials-16.0-0 创建AuthService 审核服务

public class AuthService {

    private static Map authMap = new ConcurrentHashMap();

    //查询审核结果(queryAuthInfo)
    public static Date queryAuthInfo(String uId, String orderId) {
        return authMap.get(uId.concat(orderId));
    }

    //处理审核(auth)
    public static void auth(String uId, String orderId) {
        //由谁审核的和审核的单子ID作为唯一key值记录到内存Map结构中
        authMap.put(uId.concat(orderId), new Date());
    }
}

创建tutorials-16.0-1 模块 AuthController 实现审核.

public class AuthController {

    private SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 时间格式化

    public AuthInfo doAuth(String uId, String orderId, Date authDate) throws ParseException {
        //三级审批
        Date date = AuthService.queryAuthInfo("1015", orderId);
        if (date == null) return new AuthInfo("0001", "单号: ", orderId, " 状态: 待三级审批负责人 ", "王工");

        // 二级审批  在六月1号到25号之间的 , 需要二级审批
        if (authDate.after(f.parse("2020-06-01 00:00:00")) && authDate.before(f.parse("2020-06-25 23:59:59"))){
            date = AuthService.queryAuthInfo("1012", orderId);
            if (date == null) return new AuthInfo("0001", "单号: ", orderId, " 状态: 待二级审批负责人 ", "张经理");
        }

        // 一级审批
        if (authDate.after(f.parse("2020-06-11 00:00:00")) && authDate.before(f.parse("2020-06-20 23:59:59"))) {
            date = AuthService.queryAuthInfo("1013", orderId);
            if (null == date) return new AuthInfo("0001", "单号:", orderId, " 状态:待一级审批负责人 ", "段总");
        }
        return new AuthInfo("0001", "单号: ", orderId, " 状态: 审批完成");
    }
}

创建测试类ApiTest

public class ApiTest {

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

    @Test
    public void test_AuthController() throws ParseException {
        AuthController authController = new AuthController();

        // 模拟三级负责人审批
        logger.info("测试结果: {}", JSON.toJSONString(authController.doAuth("周杰伦", "1000657570", new Date())));
        logger.info("测试结果:{}", "模拟三级负责人审批,王工");
        AuthService.auth("1000013", "1000998004813441");

        // 模拟二级负责人审批
        logger.info("测试结果: {}", JSON.toJSONString(authController.doAuth("林俊杰", "1000657570", new Date())));
        logger.info("测试结果: {}", "模拟二级负责人审批,张经理");
        AuthService.auth("1000013", "1000998004813441");

        // 模拟一级负责人审批
        logger.info("测试结果:{}", JSON.toJSONString(authController.doAuth("小傅哥", "1000998004813441", new Date())));
        logger.info("测试结果:{}", "模拟一级负责人审批,段总");
        AuthService.auth("1000011", "1000998004813441");

        logger.info("测试结果:{}", "审批完成");
    }
}

控制台打印如下 :

22:13:59.104 [main] INFO  com.thc.design.ApiTest - 测试结果: {"code":"0001","info":"单号: 1000657570 状态: 待三级审批负责人 王工"}
22:13:59.107 [main] INFO  com.thc.design.ApiTest - 测试结果:模拟三级负责人审批,王工
22:13:59.108 [main] INFO  com.thc.design.ApiTest - 测试结果: {"code":"0001","info":"单号: 1000657570 状态: 待三级审批负责人 王工"}
22:13:59.108 [main] INFO  com.thc.design.ApiTest - 测试结果: 模拟二级负责人审批,张经理
22:13:59.108 [main] INFO  com.thc.design.ApiTest - 测试结果:{"code":"0001","info":"单号: 1000998004813441 状态: 待三级审批负责人 王工"}
22:13:59.108 [main] INFO  com.thc.design.ApiTest - 测试结果:模拟一级负责人审批,段总
22:13:59.108 [main] INFO  com.thc.design.ApiTest - 测试结果:审批完成
使用责任链模式的写法

创建tutorials-16.0-2模块 创建AuthInfo类 责任链中返回对象定义

public class AuthInfo {

    private String code;
    private String info = "";

    public AuthInfo(String code, String ...infos) {
        this.code = code;
        for (String str:infos){
            this.info = this.info.concat(str);
        }
    }

    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;
    }
}

创建AuthLink类 链路抽象类定义

public abstract class AuthLink {

    // 时间格式化
    protected SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    protected String levelUserId;
    protected String levelUserName;
    private AuthLink next;

    public AuthLink(String levelUserId, String levelUserName) {
        this.levelUserId = levelUserId;
        this.levelUserName = levelUserName;
    }

    public AuthLink next() {
        return next;
    }

    public AuthLink appendNext(AuthLink next) {
        this.next = next;
        return this;
    }

    public abstract AuthInfo doAuth(String uId, String orderId, Date authDate);
}

一级审核

public class Level1AuthLink extends AuthLink {

    public Level1AuthLink(String levelUserId, String levelUserName) {
        super(levelUserId, levelUserName);
    }

    @Override
    public AuthInfo doAuth(String uId, String orderId, Date authDate) {
        Date date = AuthService.queryAuthInfo(levelUserId, orderId);
       // 第一个审核类中会先判断是否审核通过,如果没有审核通过则返回结果给调用方,引导去审核。
        // (这里简单模拟审核后 时间信息不为空,作为判断条件)
        if (date == null) {
            return new AuthInfo("0001", "单号: ", orderId, " 状态: 待一级审批负责人 ", levelUserName);
        }
        AuthLink next = super.next();
        if (next == null) {
            // 判断完成后获取下一个审核节点;super.next();,如果不存在下一个节点,则直接返回结果。
            return new AuthInfo("0000", "单号: ", orderId, " 状态: 一级审批完成负责人", " 时间: ", f.format(date), "审批人: ", levelUserName);
        }

        return next.doAuth(uId, orderId, authDate);
    }
}

二级审核

public class Level2AuthLink extends AuthLink {
    private Date beginDate = f.parse("2020-06-11 00:00:00");
    private Date endDate = f.parse("2020-06-20 23:59:59");

    public Level2AuthLink(String levelUserId, String levelUserName) throws ParseException {
        super(levelUserId, levelUserName);
    }

    @Override
    public AuthInfo doAuth(String uId, String orderId, Date authDate) {
        Date date = AuthService.queryAuthInfo(levelUserId, orderId);
        if (date == null) {
            return new AuthInfo("0001", "单号: ", orderId, " 状态: 待二级审批负责人: ", levelUserName);
        }
        AuthLink next = super.next();
        if (null == next) {
            return new AuthInfo("0000", "单号:", orderId, " 状态:二级审批完成负责人", " 时间:", f.format(date), " 审批人:", levelUserName);
        }
        // 之后是根据不同的业务时间段进行判断是否需要,二级和一级的审核。
        if (authDate.before(beginDate) || authDate.after(endDate)) {
            return new AuthInfo("0000", "单号:", orderId, " 状态:二级审批完成负责人", " 时间:", f.format(date), " 审批人:", levelUserName);
        }
        // 最后返回下一个审核结果;next.doAuth(uId, orderId, authDate)
        return next.doAuth(uId, orderId, authDate);
    }
}

三级审核.

public class Level3AuthLink extends AuthLink {

    private Date beginDate = f.parse("2020-06-11 00:00:00");
    private Date endDate = f.parse("2020-06-20 23:59:59");

    public Level3AuthLink(String levelUserId, String levelUserName) throws ParseException {
        super(levelUserId, levelUserName);
    }

    @Override
    public AuthInfo doAuth(String uId, String orderId, Date authDate) {
        Date date = AuthService.queryAuthInfo(levelUserId, orderId);
        if (null == date) {
            return new AuthInfo("0001", "单号: " + orderId, " 状态: 待三级审批负责人 ", levelUserName);
        }
        AuthLink next = super.next();
        if (null == next) {
            return new AuthInfo("0000", "单号:", orderId, " 状态:三级审批负责人完成", " 时间:", f.format(date), " 审批人:", levelUserName);
        }

        if (authDate.before(beginDate) || authDate.after(endDate)) {
            return new AuthInfo("0000", "单号:", orderId, " 状态:三级审批负责人完成", " 时间:", f.format(date), " 审批人:", levelUserName);
        }
        return next.doAuth(uId, orderId, authDate);
    }
}

测试类 :

public class ApiTest {

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

    @Test
    public void test_AuthLink() throws ParseException {
        /**
         * 责任链创建,实际的业务中会包装到控制层;
         * AuthLink authLink = new Level3AuthLink("1000013", "王工") .appendNext(new Level2AuthLink("1000012", "张经理") .appendNext(new Level1AuthLink("1000011", "段总")));
         * 通过把不同的责任节点进行组装,构成一条完整业务的责任链。
         */
        AuthLink authLink = new Level3AuthLink("1003", "王工")
                .appendNext(new Level2AuthLink("1002", "张经理"))
                .appendNext(new Level1AuthLink("1001", "段总"));

        logger.info("测试结果: {}", JSON.toJSONString(authLink.doAuth("谷爱凌", "10000522", new Date())));

        // 模拟三级负责人审批
        AuthService.auth("1003", "10000522");
        logger.info("测试结果:{}", "模拟三级负责人审批,王工");
        /**
         * 接下里不断的执行查看审核链路authLink.doAuth(...),通过返回结果对数据进行3、2、1级负责人审核,直至最后审核全部完成。
         */
        logger.info("测试结果:{}", JSON.toJSONString(authLink.doAuth("谷爱凌", "10000522", new Date())));

        // 模拟二级负责人审批
        AuthService.auth("1002", "10000522");
        logger.info("测试结果:{}", "模拟二级负责人审批,张经理");
        logger.info("测试结果:{}", JSON.toJSONString(authLink.doAuth("谷爱凌", "10000522", new Date())));

        // 模拟一级负责人审批
        AuthService.auth("1001", "10000522");
        logger.info("测试结果:{}", "模拟一级负责人审批,段总");
        logger.info("测试结果:{}", JSON.toJSONString(authLink.doAuth("谷爱凌", "10000522", new Date())));
    }

通过把不同的责任节点进行组装,构成一条完整业务的责任链。

AuthLink authLink = new Level3AuthLink("1003", "王工")
 .appendNext(new Level2AuthLink("1002", "张经理"))
 .appendNext(new Level1AuthLink("1001", "段总"));

运行后结果如下

22:32:10.860 [main] INFO  com.thc.design.test.ApiTest - 测试结果: {"code":"0001","info":"单号: 10000522 状态: 待三级审批负责人 王工"}
22:32:10.864 [main] INFO  com.thc.design.test.ApiTest - 测试结果:模拟三级负责人审批,王工
22:32:10.864 [main] INFO  com.thc.design.test.ApiTest - 测试结果:{"code":"0000","info":"单号:10000522 状态:三级审批负责人完成 时间:2022-03-28 22:32:10 审批人:王工"}
22:32:10.864 [main] INFO  com.thc.design.test.ApiTest - 测试结果:模拟二级负责人审批,张经理
22:32:10.864 [main] INFO  com.thc.design.test.ApiTest - 测试结果:{"code":"0000","info":"单号:10000522 状态:三级审批负责人完成 时间:2022-03-28 22:32:10 审批人:王工"}
22:32:10.864 [main] INFO  com.thc.design.test.ApiTest - 测试结果:模拟一级负责人审批,段总
22:32:10.864 [main] INFO  com.thc.design.test.ApiTest - 测试结果:{"code":"0000","info":"单号:10000522 状态:三级审批负责人完成 时间:2022-03-28 22:32:10 审批人:王工"}

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

微信扫码登录

0.0425s