巧用设计模式,提升代码逼格

首先,来思考一个场景(以下单为例)。如果一个下单的请求,调用的服务比较多,也就是一个请求的调用链比较长,这时候该怎么去设计我们的程序?实现的方法多种多样,比较low的方法就是把所有服务调用都写到一起,这是不推荐的,巧用设计模式瞬间提高你代码逼格。

一个电商的下单流程一般包括,订单参数校验、调用第三方服务下单、保存订单到本地数据库、保存订单操作日志等等操作。下面用代码来模拟一下这个流程。

一,创建三个处理器,分别为前置处理器、中间处理器、后置处理器,并实现有序接口保证一个处理器有多一个服务调用时,可以顺序调用服务。

/**
 * 前置处理器
 *
 * @Author: guandezhi
 * @Date: 2019/5/25 8:06 PM
 */
public interface Preprocessor<T> extends Sort {

    /**
     * 校验操作
     *
     * @param t
     */
    void validate(T t);
}
/**
 * 中间处理器
 *
 * @Author: guandezhi
 * @Date: 2019/5/25 8:06 PM
 */
public interface MiddlerProcessor<T> extends Sort {

    /**
     * 调用服务
     *
     * @param t
     */
    void invoke(T t);
}
/**
 * 后置处理器
 *
 * @Author: guandezhi
 * @Date: 2019/5/25 8:10 PM
 */
public interface AfterProcessor<T> extends Sort {

    /**
     * 保存操作
     *
     * @param t
     */
    void save(T t);
}

其中有序接口为:

/**
 * 有序接口
 *
 * @Author: guandezhi
 * @Date: 2019/5/25 8:11 PM
 */
public interface Sort {

    default int getSorted() {
        return 0;
    }
}

二,创建一个处理器增强器,将处理器放到集合中备用

/**
 * @Author: guandezhi
 * @Date: 2019/5/26 12:00 AM
 */
@Data
public class ProcessorBuilder {

    private List<Preprocessor> preprocessorList = new ArrayList<>();

    private List<MiddlerProcessor> middlerProcessorList = new ArrayList<>();

    private List<AfterProcessor> afterProcessorList = new ArrayList<>();

    private ProcessorData processorData;

    public ProcessorBuilder(Object object) {
        this.processorData = ProcessorData.builder().Data(object).resultVo(new ResultVo()).build();
    }

    public ServerChain build() {
        return new ServerChain(preprocessorList, middlerProcessorList, afterProcessorList, processorData);
    }

    /**
     * 通过服务类型将处理器装入集合中
     *
     * @param clazz
     */
    public void addProcessors(Class clazz) {
        Object serviceBean = ApplicationContextUtil.getBean(clazz);
        if (serviceBean instanceof Preprocessor) {
            preprocessorList.add((Preprocessor) serviceBean);
        } else if (serviceBean instanceof MiddlerProcessor) {
            middlerProcessorList.add((MiddlerProcessor) serviceBean);
        } else {
            afterProcessorList.add((AfterProcessor) serviceBean);
        }
    }
}

这里的ProcessorData为调用链之间传递的参数:

/**
 * @Author: guandezhi
 * @Date: 2019/5/26 12:01 AM
 */
@Data
@Builder
public class ProcessorData<T> {

    /**
     * 入参
     */
    private T Data;

    /**
     * 返回结果
     */
    private ResultVo<T> resultVo;


    public ResultVo<T> getResultVo() {
        return resultVo;
    }

    public void setResultVo(ResultVo<T> resultVo) {
        this.resultVo = resultVo;
    }
}

三,创建服务器调用链,服务的调用就在这里完成

/**
 * 服务器链
 *
 * @Author: guandezhi
 * @Date: 2019/5/25 11:58 PM
 */
@Data
@AllArgsConstructor
public class ServerChain {

    private List<Preprocessor> preprocessorList;

    private List<MiddlerProcessor> middlerProcessorList;

    private List<AfterProcessor> afterProcessorList;

    private ProcessorData processorData;

    /**
     * 按顺序调用服务器链,每个处理器可能有多个服务顺序调用
     */
    public void process() {
        preprocessorList.stream().sorted((Preprocessor p1, Preprocessor p2) -> p1.getSorted() - p2.getSorted())
                .forEach(p -> p.validate(processorData));
        middlerProcessorList.stream().sorted((MiddlerProcessor p1, MiddlerProcessor p2) -> p1.getSorted() - p2.getSorted())
                .forEach(p -> p.invoke(processorData));
        afterProcessorList.stream().sorted((AfterProcessor p1, AfterProcessor p2) -> p1.getSorted() - p2.getSorted())
                .forEach(p -> p.save(processorData));
    }

}

其中ApplicationContextUtil用于获取服务对象,如下:

/**
 * @Author: guandezhi
 * @Date: 2019/5/26 12:09 AM
 */
@Component
public class ApplicationContextUtil implements ApplicationContextAware {


    private static ApplicationContext applicationContext;

    /**
     * 通过name获取 Bean.
     *
     * @param name
     * @return
     */
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    /**
     * 通过class获取Bean.
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    /**
     * 通过name及Clazz返回指定的Bean
     *
     * @param name
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }

    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 获取applicationContext
     *
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
}

四,创建四个handler用来具体业务的操作,分别ValidateOrderHandler、CreateOrderHandler、SaveOrderHandler、SaveOrderLogHandler


/**
 * 校验订单
 *
 * @Author: guandezhi
 * @Date: 2019/5/25 8:13 PM
 */

@Slf4j
@Service
public class ValidateOrderHandler implements Preprocessor<ProcessorData<CreateOrderParam>> {


    public void validate(ProcessorData<CreateOrderParam> processorData) {

        CreateOrderParam createOrderParam = processorData.getData();

        if (createOrderParam == null) {
            processorData.getResultVo().setCode(MsgCodeEnum.FAIL.getCode());
            return;
        }

        if (StringUtils.isEmpty(createOrderParam.getMobile())) {
            processorData.getResultVo().setCode(MsgCodeEnum.FAIL.getCode());
            processorData.getResultVo().setMsg("订单手机号不能为空");
            return;
        }
        if (StringUtils.isEmpty(createOrderParam.getBuyerName())) {
            processorData.getResultVo().setCode(MsgCodeEnum.FAIL.getCode());
            processorData.getResultVo().setMsg("购买人不能为空");
            return;
        }

        //TODO 订单其他入参校验

        log.info("订单校验完成");
    }
}
/**
 * 调用第三方服务,创建订单
 *
 * @Author: guandezhi
 * @Date: 2019/5/25 8:16 PM
 */
@Slf4j
@Service
public class CreateOrderHandler implements MiddlerProcessor<ProcessorData<CreateOrderParam>> {


    public void invoke(ProcessorData<CreateOrderParam> processorData) {

        if (!MsgCodeEnum.SUCCESS.getCode().equals(processorData.getResultVo().getCode())) {
            log.info(processorData.getResultVo().getMsg());
            return;
        }

        //TODO 调用第三方服务下单
        log.info("调用第三方服务下单完成");
    }
}

​
/**
 * 保存订单到数据库
 *
 * @Author: guandezhi
 * @Date: 2019/5/25 8:18 PM
 */
@Slf4j
@Service
public class SaveOrderHandler implements AfterProcessor<ProcessorData<CreateOrderParam>> {

    public void save(ProcessorData<CreateOrderParam> processorData) {

        if (!MsgCodeEnum.SUCCESS.getCode().equals(processorData.getResultVo().getCode())) {
            return;
        }
        //TODO 此处添加保存订单操作
        log.info("保存订单到数据库完成");
    }

    @Override
    public int getSorted() {
        return 10;
    }

}
/**
 * 保存操作订单日志
 *
 * @Author: guandezhi
 * @Date: 2019/5/25 8:21 PM
 */
@Slf4j
@Service
public class SaveOrderLogHandler implements AfterProcessor<ProcessorData<CreateOrderParam>> {

    public void save(ProcessorData<CreateOrderParam> processorData) {

        if (!MsgCodeEnum.SUCCESS.getCode().equals(processorData.getResultVo().getCode())) {
            return;
        }
        //TODO 此处记录订单操作日志
        log.info("保存订单操作日志完成");

    }

    @Override
    public int getSorted() {
        return 20;
    }
}

五,创建订单服务,通过服务调用链来处理请求。

/**
 * @Author: guandezhi
 * @Date: 2019/5/26 1:24 AM
 */
@Slf4j
@Service
public class OrderService {

    @Autowired
    private ValidateOrderHandler validateOrderService;

    @Autowired
    private CreateOrderHandler createOrderService;

    @Autowired
    private SaveOrderHandler saveOrderService;

    @Autowired
    private SaveOrderLogHandler saveOrderLogService;


    public ResultVo createOrder(CreateOrderParam createOrderParam) {
        ResultVo resultVo = new ResultVo();
        ProcessorBuilder processorBuilder = new ProcessorBuilder(createOrderParam);
        processorBuilder.addProcessors(ValidateOrderHandler.class);
        processorBuilder.addProcessors(CreateOrderHandler.class);
        processorBuilder.addProcessors(SaveOrderHandler.class);
        processorBuilder.addProcessors(SaveOrderLogHandler.class);
        ServerChain serverChain = processorBuilder.build();
        serverChain.process();
        return resultVo;
    }
}

六,做个简单的测试

  1.正常情况下的日志,服务按顺序调用。

2019-05-26 21:29:43.542  INFO 798 --- [nio-8080-exec-2] c.g.p.s.o.handler.ValidateOrderHandler   : 订单校验完成
2019-05-26 21:29:43.542  INFO 798 --- [nio-8080-exec-2] c.g.p.s.o.handler.CreateOrderHandler     : 调用第三方服务下单完成
2019-05-26 21:29:43.543  INFO 798 --- [nio-8080-exec-2] c.g.p.s.order.handler.SaveOrderHandler   : 保存订单到数据库完成
2019-05-26 21:29:43.543  INFO 798 --- [nio-8080-exec-2] c.g.p.s.o.handler.SaveOrderLogHandler    : 保存订单操作日志完成

2.参数校验不通过或者其他异常时的日志,此时服务没有往下走,直接返回了。

2019-05-29 01:40:21.581  INFO 4099 --- [nio-8080-exec-7] c.g.p.s.o.handler.CreateOrderHandler     : 订单手机号不能为空

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值