1.当一块庞大的逻辑需要用到很多if else,很可能一个判断括号中的代码就有跨越两个屏幕,那么它的阅读性和可维护性都会很低, 有什么办法改善呢?
例:有三种会员进行判断
public Double discount(BigDecimal orderPrice, String memberType) {
if (memberType.equals("黄金会员")) {
if (orderPrice.compareTo(new BigDecimal(100)) > -1) {
//一百行代码 balala ...
return 0.65;
}
return 0.7;
}
if (memberType.equals("白银会员")) {
//一百行代码 balala ...
return 0.8;
}
if (memberType.equals("黄铜会员")) {
if (true) {
//balabala
}
//一百行代码 balala ...
return 0.9;
}
return 1.0;
}
使用策略模式来拆分三种会员的业务代码:
首先,创建一个接口,及它的三个会员的实现类,然后将各自业务拆分到实现类中
public interface UserPayService {
public Double discount(BigDecimal orderPrice);
}
@Service
public class BrassVipPayServiceImpl implements UserPayService {
@Override
public Double discount(BigDecimal orderPrice) {
//一百行代码 balala ...
return 0.9;
}
}
@Service
public class GoldVipPayServiceImpl implements UserPayService {
@Override
public Double discount(BigDecimal orderPrice) {
if (orderPrice.compareTo(new BigDecimal(100)) > -1) {
//一百行代码 balala ...
return 0.65;
}
return 0.7;
}
}
@Service
public class SilverVipPayServiceImpl implements UserPayService {
@Override
public Double discount(BigDecimal orderPrice) {
//一百行代码 balala ...
return 0.8;
}
}
然后在使用的时候,发现好像并没有干掉if else, 因为你无法对service 进行自动装配
public Double discount2(BigDecimal orderPrice, String memberType) {
if (memberType == "黄金会员") {
UserPayService strategy = applicationContext.getBean(GoldVipPayServiceImpl.class);
return strategy.discount(orderPrice);
}
if (memberType == "白银会员") {
UserPayService strategy = applicationContext.getBean(BrassVipPayServiceImpl.class);
return strategy.discount(orderPrice);
}
if (memberType == "黄铜会员") {
UserPayService strategy = applicationContext.getBean(SilverVipPayServiceImpl.class);
return strategy.discount(orderPrice);
}
return 1.0;
}
换一个思路,既然无法自动装配。那好像可以用一个Map将Servie存储起来,然后通过key获取
首先创建一个工厂类
@Component
public class UserPayServiceFactory {
private static Map<String, UserPayService> services = new ConcurrentHashMap<String,UserPayService>();
public static UserPayService getByUserType(String type){
return services.get(type);
}
public static void register(String userType,UserPayService userPayService){
services.put(userType,userPayService);
}
}
然后在Servie实现类中继承 InitializingBean 接口
@Service
public class BrassVipPayServiceImpl implements UserPayService, InitializingBean {
@Override
public Double discount(BigDecimal orderPrice) {
//一百行代码 balala ...
return 0.9;
}
@Override
public void afterPropertiesSet() throws Exception {
UserPayServiceFactory.register("黄铜会员",this);
}
}
@Service
public class SilverVipPayServiceImpl implements UserPayService, InitializingBean {
@Override
public Double discount(BigDecimal orderPrice) {
//一百行代码 balala ...
return 0.8;
}
@Override
public void afterPropertiesSet() throws Exception {
UserPayServiceFactory.register("白银会员",this);
}
}
............
实现InitializingBean 接口 会有一个afterPropertiesSet()方法。Spring 在初始化Bean的时候会调用它,也就是说,Spring 在初始化这个实现类的时候,也就将它放入了工厂类的Map中。然后我们调用起来就比较方便了。
@Test
void contextLoads() {
UserPayService strategy = UserPayServiceFactory.getByUserType("黄金会员");
System.out.println(strategy.discount(new BigDecimal(300)));
}
完工