赣州新闻网

首页 / 科技

记一次项目代码重构:使用Spring容器干掉if判断

2020-03-28 · 赣州新闻网 · 科技


记一次项目代码重构:使用Spring容器干掉if判断

这是在一次公司项目中进行重构时,一些复杂业务时想到的一个去掉一些if else的办法。能够使代码逻辑更加清晰,减少一些业务上的耦合。

业务说明

我所在的是一个做保险的项目组,这次重构是针对V e O c P o H其中的u D k E @ ? 6保费计算和核保的业务。

项目重构之前,在保t * q 6 T费计: i a & a算的接口中,有大量的条件判断语句) W Q ( ?来判断这次进行保费计算的产品是哪一个,然后调用该产品的保费计算方法。代码大致看起0 N : d 0来就是这个样子:

//产品编号
Strins ^ + &g product = \"123123\";
if F f @ e = ? * Y m(product.equals(\"11111\")) {
} else if (product.equals(\"11111\")) {
  &ny ) E e U {bsp; //使用产品编` 3 h , Z号是11! / N Q x Q z $111的serviK ) u oce类9 H 8 3 T G i 9进行保费计算
  &nu $ :bsp; // 
} else if 8 J D v } Z H (product.equals(\"22222\")) {
    //使用产品编号是22222的service类进行保费计算
    // 
} else {
    //执行其他的保费计算
}

这些通过一个编1 / v h y P号进行判断并执行特定代码的方法在项目中到处都是,一旦添加N A . d W @ 2 h g了新的产品,或者产品在一些特定销售渠道中有特定的一些操作(比如有一些折扣啊什么的)就要在代码的各种关键地方添加一堆 if eles,大大影响w 9 S了代码的可读性和可维护性。常常是修改了一处代码,影响到很x e D d 3 y ( 3 P多别的地方,造成一u X . . @ g些看起来很奇怪的bug。

所以我在接手这个项目的时候想到了重构。希] C 6 i Y Q 0@param premiumInfo
     * @return
     */
  &nZ e c 2 %bsp; @Override
 &n: + Ibsp; &nO Y R qbsp;public Result % z ? u U ] |;calculate(Param param) {
    K ~ u h Q g s ^ 8 &nbsw ! ? y l B `p; &nbs 6 x B ] F { _p;//将共有的实现写在这里
  b z ) u  }
}

这样在新添加一个实现类的时候只要继承这个抽象类,重写其中的某些方法就可以了。这时我们可能有很多实现类,比如:

  • PremiumCalce 1 ( 8 , F @ 1ulateP001Impl.javu 3 | ! ^ Ha
  • Pre* Y _ * 2miumCalculateP002Impl.java
  • PremiumCalculateP003Impl.java
  • PremiumCalculateP004Impl.java

这时就可以m T b U在执行保费计算的时候根据不同的产品调用不同的实现。每个实现类只写一个产品的业务就行,类之间相互不m . 1 / -影响。在新添加产品的时候也是只需要添加一3 V R ; F e个新的实现类就好了。

但是这样还有问题

但是这样还是有问题的,因为还是要在业务代码中写一 n j g p堆的a + 7if else 来判断这次到底需要哪一个实现类来D } O G执行保费计算,这时可以写一个工厂类。根据传入的产品编号或者别的什么参数,返回特定的一个实现类,像是这样:

/**
 * 保费计算接口工厂类
 */
@ServiceF 9 C g - D E
public class PremiumCa: p R _ T j .lculateFactory&nbsy D M & X H $ t ;p;{

    @Autowired
    @Qualifier(\"premiumCalculateP0001\")
 &n - { o 3 o P 5 ebsp;  private PremiumCalculate premiF | F = eu/ M ] 4 ) ; ] mCalculateP0001;

    @Autowired
    @Qualifier(\"prR / $ ^ # & hemiumCalculateP0002\")
  &nbsv ! 2 O Rp;&nb8 B # ^ csu * H z H { : Qp;private PremiumCalculath a l 7 @ .e premiumCalculateP0002;

    @Autowired
 &nbsz 2 zp;  @Qualifier(\"premiumCalculateP0003\")
    pra E ! & bivate PremiumCalculate premiumCalculateP0003;

&0 4 z 4 ! d n ]nbsp;&A 1 xnbsp;  @Autowired
    @Qualifier(\"premiumCalcuR m `lateP0004\")
&nbs9 f Yp; c M u  private PremiumCalculate premiumCalculateP0004;

   &nbe Q g usp;。。。。其他的保费计算实现对象

    public PremiumCalculate getPremiumCalculate(Stringq b : $ 9 productCode) {

    x O = =;    if (productCode.equals(\"P0001\")) {
     &nbsw O _ P $p;&/ P X @ ^ ?nbsp;    &nbsT R ip;return premiumCalculateP0001;
        } else if ()z s z r # 2 F , k {
           //其他的条件下,返回其他的对象
        }
 % V I 0 I q   }

}

添加了工厂类之后,我们在获取保费计算对象的时候只需要调用getPremiub ; J M D omCalcula 9 - ete()方法就可以了,具体返回哪一个实现对象,就交给工厂类来处理。可以精简调用保费计算时的代码。

还是免不了写if else,改造PremiumCalculateFactB m Hory

在提供了工厂类之后,还是免不了写很多的条( ` A件判断,只不过是把所有的条件判断写在了一起。这时随着产品数量的增多,if else 也会不停地增多,维护起来依然费劲。工厂等设计模式,参考:设计模式内容聚合

这里spring容器就可以排上用场了。spring中有一个BeanFactory对象,也是一个工厂,我z P # N I f | .们可以用它来改造PremiumCalcP 0 g P tulateFact$ 8 n b ! p Z 5 Iory。

首先我们在编写各个产品对应的保费计算实现类的时候都会将它注册进spring容器中,成为一个bean。我们需要给这个bean指定一个名称比如:

//在这里指定bean的名称
@Service(\"PremiumCalculate:\"+产品编号)
public class PremiumCalculat4 F ( d G ? h }eP0001Impl&nb! @ X sp;implements PremiumCalculate {
    。。。
}

然后修改PremiumCalculateFactory

/**
 * 保费计算接口工厂类
 */
@Service
public class PremiumCa, e o t ( Y % m Tlculate% 4 QFactoryX ( [ _ r n {
&o O P 4 } 7 0nbsp;   @Autowired
    private BeanFactory beanFactory;

    public PremiumCalculate getPremb # 3 diumCalculate(String productCode) {
        Object bean = beanFactory.getBean(\"PremiumCalculate:\"&nD 4 } d 8 |bsp;+ productCode);
  &n^ S O i * f Kbsp;    &nbs( K F ? K 7 Gp;if (bean instanceof PremiumCalculate)&nbsu z 5p;{
   r Q T n;    &nbi X A . =sp;  &- t y . ? 0 }bsp;+&nZ h t $ 8 ) g Xbsp;productCode);
   &nbr 5 G - s 4码相互不关联,维护0 e M和添加产品时也能减少工作量,还是比较成功的。

不足

这样写会有一个比较大的问题,就是在产品数量增B Y $ )多的时候,java文件数量也会随之变多。但是目前的业务中产品数量还可以忍受。由于产品配置功能的出现,大部分产y i T h品都可以通过数据库配置出来。这里只是写配不出来的一部分,所以这种模式还是可行的。


Suh U M G D I . { 4dofx改进方法:

在PremiumCalculate中添加一个supportProdut q P 3umCalculate:

@Autowired
private List<o % v & x /Prez E /miumCalculate> calcul^ X c t X ; L 7 .ates

最后遍历这* _ R 8 h _ r个list通过supportProduct来判断。

Java知音,专注于Java实用文章推送,不容错过!

来源:cnblogs.H k ` ; P S ? 8com/hebaibai/p/11095590.html

项目工作工厂文章接口销售全南寻乌判断