您的位置:首页 > 编程语言

利用策略模式和工厂模式优化代码中过多的if-else

2020-01-12 23:17 337 查看

​ 在公司经常会遇到一些需要做一连串相似的业务逻辑判断需求,比如使用不同支付方式实现商品打折、商店根据客户的vip等级给予客户不同的优惠政策之类的业务场景。假设现在我们接到一个需求,根据客户的VIP等级,给与不同的优惠政策:

// VIP1 消费1000 ~ 2000,9折优惠, 消费2000~5000,8折优惠,消费5000~10000,7折优惠, 消费10000~,6折优惠
static String VIP1 = "VIP1";

// VIP2 消费1000 ~ 2000,8.5折优惠, 消费2000~5000,7.5折优惠,消费5000~10000,6.5折优惠,消费10000~,5.5折优惠
static String VIP2 = "VIP2";

// VIP3 消费1000 ~ 2000,8折优惠, 消费2000~5000,7折优惠,消费5000~10000,6折优惠, 消费10000~,5折优惠
static String VIP3 = "VIP3";

// VIP4 消费1000 ~ 2000,7.5折优惠, 消费2000~5000,6.5折优惠,消费5000~10000,5.5折优惠, 消费10000~,4.5折优惠
static String VIP4 = "VIP4";

// VIP5 消费1000 ~ 2000,7折优惠, 消费2000~5000,6折优惠,消费5000~10000,5折优惠, 消费10000~,4折优惠
static String VIP5 = "VIP5";

// VIP6 消费1000 ~ 2000,6.5折优惠, 消费2000~5000,5.5折优惠,消费5000~10000,4.5折优惠, 消费10000~,3.5折优惠
static String VIP6 = "VIP6";

现在商店来了一个客户,我们需要根据客户的会员等级实现不同的优惠策略。通常使用if-else代码如下:

static BigDecimal PRICE1000 = new BigDecimal(1000);
static BigDecimal PRICE2000 = new BigDecimal(2000);
static BigDecimal PRICE5000 = new BigDecimal(5000);
static BigDecimal PRICE10000 = new BigDecimal(10000);
public BigDecimal getPrice(Client client, BigDecimal price){
BigDecimal realPrice = price;
if(VIP1.equals(client.getType())){
if(PRICE1000.compareTo(price) < 0 && PRICE2000.compareTo(price) >= 0){
realPrice = new BigDecimal("0.9").multiply(price);
} else if(PRICE2000.compareTo(price) < 0 && PRICE5000.compareTo(price) >= 0){
realPrice = new BigDecimal("0.8").multiply(price);
} else if(PRICE5000.compareTo(price) < 0 && PRICE10000.compareTo(price) >= 0){
realPrice = new BigDecimal("0.7").multiply(price);
} else if(PRICE10000.compareTo(price) < 0){
realPrice = new BigDecimal("0.6").multiply(price);
}
} else if(VIP2.equals(client.getType())){
//...
} else if(VIP3.equals(client.getType())){
//...
} else if(VIP4.equals(client.getType())){
//...
} else if(VIP5.equals(client.getType())){
//...
} else if(VIP6.equals(client.getType())){
//...
}
return realPrice;
}

很抱歉,实在写不下去了,重复这样子写有些累,后面VIP2~VIP6只需要仿照VIP1的优惠策略写就行,我在这里只是想要表达这种写法实在不怎么样,读者明白我的意思就行。这里可以通过使用策略模式进行优化:

// 策略接口
public interface VIP {
static BigDecimal PRICE1000 = new BigDecimal(1000);
static BigDecimal PRICE2000 = new BigDecimal(2000);
static BigDecimal PRICE5000 = new BigDecimal(5000);
static BigDecimal PRICE10000 = new BigDecimal(10000);
BigDecimal getPrice(BigDecimal price);
}

// 具体策略实现类
public class VIP1 implements VIP {
@Override
public BigDecimal getPrice(BigDecimal price) {
BigDecimal realPrice = price;
if(PRICE1000.compareTo(price) < 0 && PRICE2000.compareTo(price) >= 0){
realPrice = new BigDecimal("0.9").multiply(price);
} else if(PRICE2000.compareTo(price) < 0 && PRICE5000.compareTo(price) >= 0){
realPrice = new BigDecimal("0.8").multiply(price);
} else if(PRICE5000.compareTo(price) < 0 && PRICE10000.compareTo(price) >= 0){
realPrice = new BigDecimal("0.7").multiply(price);
} else if(PRICE10000.compareTo(price) < 0){
realPrice = new BigDecimal("0.6").multiply(price);
}
return realPrice;
}
}
// 这里只将VIP1的具体实现放了上来,其他几种策略意思差不多

public class Shop {
public BigDecimal getPrice(Client client, BigDecimal price){
VIP vip = null;
if(VIP1.equals(client.getType())){
vip = new VIP1();
} else if(VIP2.equals(client.getType())){
vip = new VIP2();
} else if(VIP3.equals(client.getType())){
vip = new VIP3();
} else if(VIP4.equals(client.getType())){
vip = new VIP4();
} else if(VIP5.equals(client.getType())){
vip = new VIP5();
} else if(VIP6.equals(client.getType())){
vip = new VIP6();
}
return vip.getPrice(price);
}
public static void main(String[] args) {
Shop shop = new Shop();
Client client = new Client();
client.setType(Shop.VIP1);
client.shopping(shop, new BigDecimal(10000));
}
}

显然,这样子代码看着舒服了一些,而且后面如果哪个VIP等级的优惠政策有了更改,我们只需要在相应的策略实现类中进行修改即可,另外之后如果添加VIP7…VIPN是只需要添加具体策略实现类就行。当然,这样也会导致后面的类文件十分多,会增添项目文件管理上的麻烦,这一点是需要我们注意的。另外,眼尖的你应该也发现了,上面的代码还是有很多if-else,具体策略类中的if-else暂时无能为力(可以使用策略模式,但是感觉使用了策略模式之后项目文件管理会变成一个巨大的麻烦),后面如果我有了方法解决这个问题,会再更新这篇文章。具体使用哪种策略时使用的if-else判断是可以利用Map来替换,Map中的key为用户VIP类型,value为具体策略类型。利用Map我们可以直接通过get方法拿到我们想要的具体策略实现类的实例,从而获取相应的方法。具体实现大体如下:

public class VIPFactory {
private static VIPFactory factory = new VIPFactory();
private VIPFactory(){}
private static Map vipMap = new HashMap<>();
static {
vipMap.put(Shop.VIP1, new VIP1());
vipMap.put(Shop.VIP2, new VIP2());
vipMap.put(Shop.VIP3, new VIP3());
vipMap.put(Shop.VIP4, new VIP4());
vipMap.put(Shop.VIP5, new VIP5());
vipMap.put(Shop.VIP6, new VIP6());
}
public static VIPFactory getInstance(){
return factory;
}
public VIP getVip(String vipType){
return (VIP) vipMap.get(vipType);
}
}

public class Shop {
public BigDecimal getPrice(Client client, BigDecimal price){
VIP vip = VIPFactory.getInstance().getVip(client.getType());
return vip.getPrice(price);
}
public static void main(String[] args) {
Shop shop = new Shop();
Client client = new Client();
client.setType(Shop.VIP1);
client.shopping(shop, new BigDecimal(10000));
}
}

具体的策略实现类我就不再赘述了,工厂使用的是单例模式。其实这个时候可以很明显到感觉代码看起来舒服多了。

  • 点赞
  • 收藏
  • 分享
  • 文章举报
灵灵林 发布了36 篇原创文章 · 获赞 4 · 访问量 814 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: