我是靠谱客的博主 寒冷红牛,最近开发中收集的这篇文章主要介绍Java 优雅地分离验证代码与业务核心代码,减少过多的if-else(优化版),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在过去的一篇文章写过《Java 优雅地分离验证代码与业务核心代码,减少过多的if-else》,利用文章中提及的方式做业务验证,在后续的开发中,慢慢演化诞生了优化版。这个优化版方式,在原来的基础上,结合对Spring IOC容器托管的对象实例处理,达到一个业务验证代码多次复用,而且拓展更好的目的。

废话不多说,看Demo。

验证接口类:Condition.java

/**
 * 业务验证接口
 * @author rocky
 */
public interface Condition<T> {

    /**
     * 验证
     * @param t 参数
     */
    void apply(T t);

}

业务验证工具类:ConditionValidator.java

/**
 * 业务验证工具类
 * @author rocky
 */
public class ConditionValidator {
	
	// 为什么这里有个默认私有构造方法?因为,ConditionValidator不允许实例化。
    private ConditionValidator() {}

    /**
     * 业务验证
     * @param t 参数
     * @param conditions 具体的业务验证
     * @param <T> 参数类型
     */
    public static <T> void apply(T t, List<Condition<T>> conditions) {
        conditions.forEach(c -> c.apply(t));
    }

    /**
     * 业务验证
     * @param t 参数
     * @param clazz 类对象
     * @param <T> 参数类型
     */
    public static <T> void apply(T t, Class< ? extends Condition<T>> clazz) {
    	// SpringContextUtils是我这边封装的Spring Ioc 容器管理的一个工具类
    	// 核心内容是org.springframework.context.ApplicationContext,有兴趣的同学可以去了解下
        Condition<T> condition = null;
        if (SpringContextUtils.containsBean(clazz)) {
            condition = SpringContextUtils.getBean(clazz);
        }
        // 为NULL,说明Spring IOC容器没有托管对象实例
        if (condition == null) {
            try {
                condition = clazz.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                throw new NullPointerException("The clazz can not instantiated");
            }
        }
        condition.apply(t);
    }

    /**
     * 业务验证
     * @param t 参数
     * @param classes 可变类参数对象
     * @param <T> 参数类型
     */
    public static <T> void apply(T t, Class<? extends Condition<T>>... classes) {
        for (Class<? extends Condition<T>> clazz : classes) {
            apply(t, clazz);
        }
    }
}

某业务验证类:BookingTimeCondition.java

/**
 * 预约时间段数据验证
 * @author rocky
 */
public class BookingTimeCondition implements Condition<BookingTime> {

    @Override
    public void apply(BookingTime bookingTime) {
    	// BookingTime是一个简单的pojo类,里面带有java bean validator的注解 
    	// hibernate-validator 验证
        ValidatorUtils.validateEntity(bookingTime);
        // 业务验证,判断预约时间是否符合数据规范
        String timeSlot = bookingTime.getTimeSlot();
        String[] timeArray = timeSlot.split("-");
        if (timeArray.length < 2) {
            throw new ValidatorException("预约时间段格式错误");
        }
        Object orderTime = bookingTime.getOrderTime();
        String orderTimeStr;
        // 这样是为了兼容不同类型的时间数据
        if (orderTime instanceof String) {
            orderTimeStr = (String) orderTime;
        } else if (orderTime instanceof Date) {
            Date date = (Date) orderTime;
            orderTimeStr = DateFormatUtils.format(date, "yyyy-MM-dd");
        } else if (orderTime instanceof LocalDate) {
            LocalDate date = (LocalDate) orderTime;
            orderTimeStr  = date.toString();
        } else {
            orderTimeStr = orderTime.toString();
        }

        String bt = orderTimeStr + " " + timeArray[1];
        Date orderDate = null;
        try {
            orderDate = DateUtils.parseDate(bt, "yyyy-MM-dd HH:mm");
        } catch (ParseException ex) {
            throw new ValidatorException("预约时间格式错误");
        }
        if (new Date().after(orderDate)) {
            throw new ValidatorException("预约时间只能在当前时间之后");
        }
    }
}

用法如下:

BookingTime bookingTime = new BookingTime(form.getOrderTime(), form.getTimeSlot());
// 验证预约时间是否合法
// 用法1,推荐这个方法
ConditionValidator.apply(bookingTime, BookingTimeCondition.class);
// 用法2,如果验证条件已有实例,可以采用这个方式复用实例,减少系统资源消耗
ConditionValidator.apply(bookingTime, Arrays.asList(new BookingTimeCondition()));

如果你的业务验证需要注入Service层或者Dao的对象去查库校验,那么实现Condition接口的子类实例需要交给Spring Ioc容器来管理。

代码如下:

/**
 * 用户账号资格验证
 * @author rocky
 */
@Component
public class UserBalanceCondition implements Condition<UserEntity> {
    
    @Resource
    private UserWalletService userWalletService;
    
    public void apply(UserEntity user) {
    	// 以下是业务验证内容,这里只是举例说明
        UserWalletEntity wallet = userWalletService.getByUserId(user.getId());
        if (userWalletService.isAllowTranfter(wallet)) {
            throw new ValidatorException("用户xx不允许操作流动资金");
        }
        ...
    }
    
}

用法:

// 执行验证操作,如果UserBalanceCondition被Spring Ioc托管,取Spring Ioc里面的实例进行运算,否则通过反射来实例化进行运算。
ConditionValidator.apply(user, UserBalanceCondition.class);

这样,在不同的子业务中,需要相同的业务验证,可以通过这样的方式,来提高代码复用率和开发效率。

最后

以上就是寒冷红牛为你收集整理的Java 优雅地分离验证代码与业务核心代码,减少过多的if-else(优化版)的全部内容,希望文章能够帮你解决Java 优雅地分离验证代码与业务核心代码,减少过多的if-else(优化版)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部