最近代码之中遇到了以下问题:在我们的商城中根据活动类型计算满减金额的问题,大致代码如下:
public class orderCalculate { public BigDecimal getDiscount(String type) { BigDecimal discount = BigDecimal.ZERO; if(type.equals("fullDiscount")){ //....................满减计算方法 } else if (type.equals("platFormDiscount")) { //....................平台满减计算方法 } else if (type.equals("coupon")) { //.....................优惠券计算方法 }else { //没有优惠 } return discount; } }
这种处理方式的缺点在于:
1.if else的判断逻辑很复杂,代码的可读性很差
2.代码的扩展性很差,一旦添加活动会造成代码大幅度修改
3.强迫症看了很难受
基于以上,尤其是第三点,我们决定对代码进行处理
首先我们不难想到利用接口的方式对代码进行优化。首先我们定义一个公共接口 Activity和他的一些实现类
public interface Activity { public BigDecimal getDiscount(BigDecimal amount); } public class fullDiscountActivity implements Activity { @Override public BigDecimal getDiscount(BigDecimal amount) { BigDecimal discount=BigDecimal.ZERO; //计算逻辑 return discount; } } public class coupon implements Activity { @Override public BigDecimal getDiscount(BigDecimal amount) { BigDecimal discount=BigDecimal.ZERO; //计算逻辑 return discount; } } @Override public BigDecimal getDiscount(BigDecimal amount) { BigDecimal discount=BigDecimal.ZERO; //计算逻辑 return discount; } public class noActivity implements Activity { @Override public BigDecimal getDiscount(BigDecimal amount) { return amount; } }
这样我们的getDiscount方法就变成了如下:
public BigDecimal getDiscount(BigDecimal amount,String type) { BigDecimal discount = BigDecimal.ZERO; if(type.equals("fullDiscount")){ fullDiscountActivity fullDiscountActivity = new fullDiscountActivity(); return fullDiscountActivity.getDiscount(amount); } else if (type.equals("platFormDiscount")) { platFormDiscount platFormDiscount = new platFormDiscount(); return platFormDiscount.getDiscount(amount); } else if (type.equals("coupon")) { coupon coupon = new coupon(); return coupon.getDiscount(amount); }else { //没有优惠 } return discount; }
这里我们把每个优惠的具体实现方法放在了各自的类中,一定程度上提高了代码的可读性。接下来我们做进一步代码优化
public BigDecimal getDiscount(BigDecimal amount,String type) { Activity activity; if(type.equals("fullDiscount")){ activity = new fullDiscountActivity(); } else if (type.equals("platFormDiscount")) { activity = new fullDiscountActivity(); } else if (type.equals("coupon")) { activity = new fullDiscountActivity(); }else { activity = new noActivity(); } return activity.getDiscount(amount); }
这样代码似乎变得含看一下了呢。但是实际上我们并没有去掉if else。我们接下来思考,我们的type字段都是放在我们的方法中处理的,我们能不能找个方法把type也作为字段传输过去,这样不就是可以去掉if else了吗。这样的话我们就需要用到工厂模式,在一个处理类中对类型进行处理并匹配到相应的活动类。
首先我们在接口中增加getType方法,为每个特定的实现类返回特定的方法
public interface Activity { public BigDecimal getDiscount(BigDecimal amount); public String getType(); } public class coupon implements Activity { @Override public BigDecimal getDiscount(BigDecimal amount) { BigDecimal discount=BigDecimal.ZERO; //计算逻辑 return discount; } @Override public String getType() { return "coupon"; } } public class fullDiscountActivity implements Activity { @Override public BigDecimal getDiscount(BigDecimal amount) { BigDecimal discount=BigDecimal.ZERO; //计算逻辑 return discount; } @Override public String getType() { return "fullDiscount"; } } public class noActivity implements Activity { @Override public BigDecimal getDiscount(BigDecimal amount) { return amount; } @Override public String getType() { return "noActivity"; } } public class platFormDiscount implements Activity { @Override public BigDecimal getDiscount(BigDecimal amount) { BigDecimal discount=BigDecimal.ZERO; //计算逻辑 return discount; } @Override public String getType() { return "platFormDiscount"; } }
接下来我们新建活动工厂类:
该类需要处理type并且能返回对应的工厂类;
public class ActivityFactory {
private Map<String, Activity> map;
private ActivityFactory() {
List<Activity> activities = new ArrayList<>();
activities.add(new coupon());
activities.add(new fullDiscountActivity());
activities.add(new platFormDiscount());
activities.add(new noActivity());
//LIST转化为map以做匹配
for (Activity activity : activities) {
map.put(activity.getType(), activity);
}
}
//静态内部类
public static class Holder {
public static ActivityFactory instance = new ActivityFactory();
}
//单例方法
public ActivityFactory getInstance() {
return Holder.instance;
}
//获取对应的活动类
public Activity getActivity(String type) {
return map.get(type);
}
}
该类主要实现了以下功能:
1.私有化构造方法,并通过getInstance获取实例来实现单例模式;
2.静态内部类加载对象
3.构造方法中把所有的活动对象根据type作为key存入map中
4.getActivity方法通过map匹配到对应的activity对象并返回
这样,我们就可以高兴的(for处女座)的来写我们的getDiscount方法了,是不是很简洁。
public BigDecimal getDiscount(BigDecimal amount,String type) {
Activity activity =ActivityFactory.getInstance().getActivity(type);
return activity.getDiscount(amount);
}