使用策略模式改造代码坏味道,让代码更有质量

一、适用场景

  在日常的代码开发过程中,你是否频繁的适用if/else、if elseif else 等这种语句,有没有想过使用设计模式来改造你的代码,让你的代码更加有质量。

  我们在开发过程中,很常见的会遇到,不同角色对资源进行不同的分配,例如:不同的用户身份(vip、svip、normal)面临不同的计价策略。

  此时面对这样的场景:

  使用策略模式改造代码坏味道,让代码更有质量  这种计价策略属于平级状态,每次根据用户的身份只会选择一种计价策略。

  未使用策略模式前的代码:

import com.shuwen.demo.service.FeeCalculationService;
import org.springframework.stereotype.Service;


@Service
public class FeeCalculationsServiceImpl implements FeeCalculationService {

    @Override
    public double feeCalculation(String type, double fee) {
        if ("vip".equals(type)){
            return fee * 0.98;
        }else if ("svip".equals(type)){
            return fee * 0.90;
        }else{
            return fee ;
        }
    }
}

   发现当我们需要对其进行扩展时,只能对原来的代码进行添加,在原来的代码上修改代码,这就是代码中的坏味道。


   我们需要去除这种代码中的坏味道,让代码清新起来,让代码的可拓展性更强,便于项目的维护和二次开发。

   现在我们将其进行改造:

    a)定义策略接口 规范策略必有内容

public interface DiscountStrategy {
  //角色类型 public String type();
  //计价策略 public double discount(double fee); }

    b)实现策略接口,编写具体的实现业务

      1)VIP用户计价策略的具体实现

import com.shuwen.demo.strategy.DiscountStrategy;
import org.springframework.stereotype.Service;

@Service
public class VipDiscountStrategy implements DiscountStrategy {
    @Override
    public String type() {
        return "vip";
    }

    @Override
    public double discount(double fee) {
        return fee * 0.98;
    }
}

      2)SVIP用户计价策略的具体实现

import com.shuwen.demo.strategy.DiscountStrategy;
import org.springframework.stereotype.Service;

@Service
public class SvipDiscountStrategy implements DiscountStrategy {
    @Override
    public String type() {
        return "svip";
    }

    @Override
    public double discount(double fee) {
        return fee * 0.70;
    }
}

      3)普通用户计价策略的具体实现

import com.shuwen.demo.strategy.DiscountStrategy;
import org.springframework.stereotype.Service;

@Service
public class NormalDiscountStrategy implements DiscountStrategy {
    @Override
    public String type() {
        return "normal";
    }

    @Override
    public double discount(double fee) {
        return fee;
    }
}

    c)将具体的策略方法,存放到map之中,方便使用

  //用map来存策略方法
    Map<String,DiscountStrategy> discountStrategyMap = new HashMap<>();
    //利用构造方法 将策略方法放到map中 此处List<DiscountStrategy> spring将自动注入策略
    public FeeCalculationServiceImpl(List<DiscountStrategy> discountStrategies) {
        for (DiscountStrategy discountStrategy : discountStrategies){
            discountStrategyMap.put(discountStrategy.type(),discountStrategy);
        }
    }

    d)具体的业务实现,就变的可拓展性极强。

import com.shuwen.demo.service.FeeCalculationService;
import com.shuwen.demo.strategy.DiscountStrategy;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class FeeCalculationServiceImpl implements FeeCalculationService {
    //用map来存策略方法
    Map<String,DiscountStrategy> discountStrategyMap = new HashMap<>();
    //利用构造方法 将策略方法放到map中 此处List<DiscountStrategy> spring将自动注入策略
    public FeeCalculationServiceImpl(List<DiscountStrategy> discountStrategies) {
        for (DiscountStrategy discountStrategy : discountStrategies){
            discountStrategyMap.put(discountStrategy.type(),discountStrategy);
        }
    }

    @Override
    public double feeCalculation(String type, double fee) {
        // 只需利用map 用key:type 找到对应的具体策略方法,直接使用即可
        // 如有需求改变,有新的用户身份 直接实现策略接口 并交由spring工厂管理即可
        DiscountStrategy discountStrategy = discountStrategyMap.get(type);
        double discount = discountStrategy.discount(fee);
        return discount;
    }
}

   这样来实现业务代码,泛泛而看是去掉了很多if else 条件判断,这样当我们的需求发生变化时,只需新增一个具体的策略方法即可。

   例如现在有一个新需求,黑卡用户需要打0.5折:

使用策略模式改造代码坏味道,让代码更有质量

    这时,我们只需要增加一个黑卡用户的计价具体策略方法即可,不需要变更原来的业务处理方法。

import com.shuwen.demo.strategy.DiscountStrategy;
import org.springframework.stereotype.Service;

@Service
public class HVipDiscountStrategy implements DiscountStrategy {
    @Override
    public String type() {
        return "hvip";
    }

    @Override
    public double discount(double fee) {
        return fee * 0.50;
    }
}

  这时,我们的代码质量大大改善,以后维护也更加轻松~

  测试调用方法具体实现:

@Test
    public void test1() {
        double vip = feeCalculationService.feeCalculation("vip", 5000);
        System.out.println("yesterday you have consumer 5000 dollars,true you have consumer "+vip);
    }

  

 

 

  

上一篇:【7】.net WebAPI Owin OAuth 2.0 密码模式验证实例


下一篇:状态机DP