打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
java笔记之消除重复代码

一、利用工程模式+模板方法,消除if...else重复代码

假如做一个购物车下单,计算商品,优惠卷、配送费价格功能,普通用户收取费用、运费跟vip、内部用户计算价格肯定不一样的。

一般代码写法:

  String userType="normal";
        if(userType.equals("normal")){
            //普通用户执行价格逻辑
        }else if(userType.equals("internalUserCart")){
            //内部用户执行
        }else {
            //其他用户执行
        }

将业务逻辑集中写在请求方法中,好点的话,可以分开创建不同类执行(用户类、vip、内部用户),这样的话有一些重复性代码,比如三个角色商品价格获取,只是返回的时候,根据业务规定计算出价格。

其实,三种购物车计算价格,可以把重复的代码放在抽象类中,不同的价格计算由子类去实现。实现方法如下:

1、创建抽象类

这里只做演示,参数、方法逻辑根据实际情况定义。

public abstract class AbstractCar {
    public void process(long userId, Map<String,Object> item){
        //大量逻辑处理代码
        log.info("计算购物车 userId:{},{}",userId,item);
    }
    //优惠卷
    protected abstract void processCouponPrice(long userId,  Map<String,Object> item);
    //配送费价格
    protected abstract void processDeliveryPrice(long userId, Map<String,Object> item);
}

2、创建普通用户,继承抽象类

@Service("normalUserCart")
public class NormalUserCart  extends AbstractCar{

//    普通用户的购物车 NormalUserCart,实现的是 0 优惠和 10% 运费的逻辑:
    @Override
    protected void processCouponPrice(long userId, Map<String, Object> item) {
        log.info("普通用户,计算优惠卷价格{}",userId);
    }

    @Override
    protected void processDeliveryPrice(long userId, Map<String, Object> item) {
        log.info("普通用户,计算配送费价格{}",userId);
    }
}

注意:添加@Service注解,后面需要通过spring容器管理,获取该对象。

3、vip用户,继承普通用户

@Slf4j
@Service("vipUserCart")
public class VipUserCart extends NormalUserCart{

//    VipUserCart,直接继承了 NormalUserCart,只需要修改多买优惠策
    @Override
    protected void processCouponPrice(long userId, Map<String, Object> item) {
       log.info("VipUserCart processCouponPrice:{}",userId);
    }

}

vip用户跟普通用户,除了优惠卷外,其他计算方式一样,所以直接继承。

4、内部用户

@Slf4j
@Service("internalUserCart")
public class InternalUserCart extends AbstractCar{

//    内部用户
    @Override
    protected void processCouponPrice(long userId, Map<String, Object> item) {
       log.info("InternalUserCart processCouponPrice:{}",userId);
    }

    @Override
    protected void processDeliveryPrice(long userId, Map<String, Object> item) {
        log.info("InternalUserCart processDeliveryPrice:{}",userId);
    }

}

5、请求方法测试

//        模拟用户类型
        String userCategory = "internalUserCart";
        AbstractCar car = applicationContext.getBean(userCategory, AbstractCar.class);
        Map<String,Object> item = new HashMap<>();
        item.put("name","car");
        item.put("price",1000);
        car.process(1,item);

这里只做模拟演示,用户类型一般通过请求参数来判断,你会发现请求类型变量值,跟@Service注解值一致。这里的方法删除了if else大量逻辑代码,直接由AbstractCar类调用,具体逻辑交给其子类实现。

这就是设计模式中的开闭原则:对修改关闭,对扩展开放。

二、利用Bean映射工具

如果一个类的属性多达数十个,但是需要DTO转换为类似的DO操作,那么出现大量的以下代码:

ComplicatedOrderDTO orderDTO = new ComplicatedOrderDTO();
ComplicatedOrderDO orderDO = new ComplicatedOrderDO();
orderDO.setAcceptDate(orderDTO.getAcceptDate());
orderDO.setAddress(orderDTO.getAddress());
orderDO.setAddressId(orderDTO.getAddressId());
orderDO.setCancelable(orderDTO.isCancelable());
orderDO.setCommentable(orderDTO.isComplainable()); //属性错误
orderDO.setComplainable(orderDTO.isCommentable()); //属性错误
orderDO.setCancelable(orderDTO.isCancelable());
orderDO.setCouponAmount(orderDTO.getCouponAmount());
orderDO.setCouponId(orderDTO.getCouponId());
orderDO.setCreateDate(orderDTO.getCreateDate());
orderDO.setDirectCancelable(orderDTO.isDirectCancelable());
orderDO.setDeliverDate(orderDTO.getDeliverDate());
orderDO.setDeliverGroup(orderDTO.getDeliverGroup());
orderDO.setDeliverGroupOrderStatus(orderDTO.getDeliverGroupOrderStatus());
orderDO.setDeliverMethod(orderDTO.getDeliverMethod());
orderDO.setDeliverPrice(orderDTO.getDeliverPrice());
orderDO.setDeliveryManId(orderDTO.getDeliveryManId());
orderDO.setDeliveryManMobile(orderDO.getDeliveryManMobile()); //对象错误
orderDO.setDeliveryManName(orderDTO.getDeliveryManName());
orderDO.setDistance(orderDTO.getDistance());
orderDO.setExpectDate(orderDTO.getExpectDate());
orderDO.setFirstDeal(orderDTO.isFirstDeal());

在赋值过程中,很容易写错、漏写造成数据不准确。可以使用BeanUtils这样Mapping工具来转换。copyProperties还可以忽略某些属性。

ComplicatedOrderDTO orderDTO = new ComplicatedOrderDTO();
ComplicatedOrderDO orderDO = new ComplicatedOrderDO();
BeanUtils.copyProperties(orderDTO, orderDO, "id");
return orderDO;

总结

第一种消除重复代码,可以考虑将相同逻辑提取到父类中,差异的逻辑通过抽象方法留给子类实现。通过类似的模板方法把相同的逻辑做成固定模板,差异的同时尽可能避免重复代码。同时使用Spring的IOC特性注入子类,来避免实例化子类时大量的if else代码。

第二种重复代码,业务中常见的DO、DTO、VO转换时大量手动赋值,容易出错。通过映射工具BeanUtils实现。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Java中干掉 “重复代码” 的技巧大全(经验总结)
重学 Java 设计模式:实战外观模式「基于SpringBoot开发门面模式中间件,统一控制接口白名单场景」
DWR3实现服务器端向客户端精确推送消息
初探Liferay Enterpriese Portal的数据类型持久化
Spring Boot (七): Mybatis极简配置
SpringBoot源码解析(一)
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服