使用策略模式改造代码坏味道,让代码更有质量
一、适用场景
在日常的代码开发过程中,你是否频繁的适用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); }