如何干掉 if else 策略+工厂

无论我们做什么业务都无法避免 if else, 但是多重又会导致很多if,今天我们来讲讲如何干掉if else 让你摆脱被if else 支配的恐惧.


 首先让我们来看看简单的if else 语句

public void test(TestUser testUser) {
if (Objects.isNull(testUser)){
System.out.println("执行业务 一");
} else {
System.out.println("执行业务 二");
}
}

  并没有什么问题.但是如果业务稍微复杂一些呢,我们再来看看
  首先贴出用户实体类

@Data
public class TestUser {
private Integer id;
private String name;
private Viplevel vipLevel;
}

  在贴出用户VIP枚举

@Getter
@AllArgsConstructor
public enum Viplevel implements Serializable, IEnum {

NOVIP(0, "普通用户","普通用户"),
VIP_LEVEL1(1, "包月会员","包月会员"),
VIP_LEVEL2(2, "季度会员","季度会员"),
VIP_LEVEL3(3, "半年会员","半年会员"),
VIP_LEVEL4(4, "年费会员","年费会员");

private final Integer code;

private final String desc;

private final String msg;

@JsonCreator
public static Viplevel jsonCreator(Integer code) {
for (Viplevel value : Viplevel.values()) {
if (value.getCode().equals(code)) {
return value;
}
}
return null;
}

@JsonValue
public Map getResult() {
Map<String, Object> map = new LinkedHashMap<String, Object>();
map.put("code", getCode());
map.put("desc", getDesc());
map.put("msg", getMsg());
return map;
}
@Override
public Serializable getValue() {
return this.code;
}
}

  再来看看业务

public double sellMoney(TestUser testUser) {
double proPrice = 3000;
double resultMoney = proPrice;
if (Objects.isNull(testUser)) {
//抛出异常
return proPrice;
} else {
if (Viplevel.NOVIP.equals(testUser.getVipLevel())) {
System.out.println("普通用户");
resultMoney = proPrice;
} else if (Viplevel.VIP_LEVEL1.equals(testUser.getVipLevel())) {
System.out.println("包月会员");
resultMoney = proPrice - 100;
} else if (Viplevel.VIP_LEVEL2.equals(testUser.getVipLevel())) {
System.out.println("季度会员");
resultMoney = proPrice - 300;
} else if (Viplevel.VIP_LEVEL3.equals(testUser.getVipLevel())) {
System.out.println("半年会员:");
resultMoney = proPrice * 0.8;
} else if (Viplevel.VIP_LEVEL4.equals(testUser.getVipLevel())) {
System.out.println("年会员:");
resultMoney = proPrice * 0.3;
}
return resultMoney;
}
}

  天哪,这只是一个简单的例子,竟然出现如此多让人懊恼的语句.那么该如何解决呢,别着急,让我们一步步来干掉讨厌的 if else
  首先思考,最终结果就是要获取到最终产品的售价,那我们就写个计算结果的方法,再让接口去继承他,这样不就能根据需求计算得到结果了吗

/**
* @author NYY
* @decription 普通用户最终产品售价
*/
public class NormalStrategy implements ComputeStrategy {
@Override
public double compute(double money) {
return money;
}
}
/**
* @author NYY
* @date 2020/6/4$
* @decription 月会员最后售价
*/
public class MonthStrategy implements ComputeStrategy {
@Override
public double compute(double money) {
return money - 100;
}
}

  ....以此类推
  那么我们最终的业务实现是这样的

private static double getResultMoney(TestUser testUser) {
double proPrice = 3000;
double resultMoney = proPrice;
if (Objects.isNull(testUser)) {
//抛出异常
return proPrice;
} else {
if (Viplevel.NOVIP.equals(testUser.getVipLevel())) {
resultMoney = new NormalStrategy().compute(proPrice);
} else if (Viplevel.VIP_LEVEL1.equals(testUser.getVipLevel())) {
resultMoney = new MonthStrategy().compute(proPrice);
}
//......
}
return resultMoney;
}

  在优化一下变成了这样

private static double getResultMoneyTwo(TestUser testUser) {
double proPrice = 3000;
double resultMoney = proPrice;
ComputeStrategy computeStrategy = null;
if (Objects.isNull(testUser)) {
//抛出异常
return proPrice;
} else {
if (Viplevel.NOVIP.equals(testUser.getVipLevel())) {
computeStrategy = new NormalStrategy();
} else if (Viplevel.VIP_LEVEL1.equals(testUser.getVipLevel())) {
computeStrategy = new MonthStrategy();
}
//......
//最后计算结果
return computeStrategy.compute(proPrice);
}
}

  什么,if else 居然还在,我们发现,它需要的不仅是计算结果,主要是根据用户类型,好吧,那我们吧用户类型也提出来

public interface ComputeStrategyTwo {
// 计算方法
double compute(double money);
//获取用户类型
Integer getUserType();
}

  接口继承时实现这两个方法

  新增的 getUserType 方法,主要用来标示该策略的type 值。

/**
* @author NYY
* @decription 普通用户
*/
public class NewNormalStrategy implements ComputeStrategyTwo{
@Override
public double compute(double money) {
return money;
}
@Override
public Integer getUserType() {
return Viplevel.NOVIP.getCode();
}
}
/**
* @author NYY
* @decription 月会员最后售价
*/
public class NewMonthStrategy implements ComputeStrategyTwo {
@Override
public double compute(double money) {
return money - 100;
}
@Override
public Integer getUserType() {
return Viplevel.VIP_LEVEL1.getCode();
}
}


  重点又来了,这时我们就再把策略的工厂加进来

/**
* @author NYY
* @decription
*/
public class ComputeStrategyFactory {
private Map<Integer, ComputeStrategyTwo> map;
public ComputeStrategyFactory() {

List<ComputeStrategyTwo> strategies = new ArrayList<>();
strategies.add(new NewNormalStrategy());//普通用户
strategies.add(new NewMonthStrategy());//包月用户
//.......

// java 8 stream流
map = strategies.stream().collect(Collectors.toMap(ComputeStrategyTwo::getUserType, computeStrategy -> computeStrategy));
}

public static class Possessor {
public static ComputeStrategyFactory instance = new ComputeStrategyFactory();
}

public static ComputeStrategyFactory getInstance() {
return Possessor.instance;
}

public ComputeStrategyTwo get(Integer type) {
ComputeStrategyTwo computeStrategyTwo = map.get(type);
return computeStrategyTwo;
}
}

  这样我们策略的工厂也有了.最终让我们看看处理业务的代码变成什么样了呢.

private static  double lastResultMoney(TestUser testUser){
double proPrice = 3000;
Objects.requireNonNull(testUser,"用户对象为空了");

ComputeStrategyTwo computeStrategyTwo = ComputeStrategyFactory.getInstance().get(testUser.getVipLevel().getCode());
if(Objects.isNull(computeStrategyTwo)){
// throw new GlobalException("用户类型未知");
// 抛出全局异常
}
return computeStrategyTwo.compute(proPrice);
}

  怎么样 最终我们通过策略+工厂的方式实现了业务,再也没看见令人讨厌的if else 语句.

  至此完结 !!! 文章未经博主同意禁止转载,转载请赋连接

posted @ 2020-06-11 00:19  java之途  阅读(638)  评论(0编辑  收藏  举报