也许我们的代码中遇到过多重判断if-else语句,但是这样的代码可读性差,并且当扩展时,违反了“开闭原则”。阿里开发规范中提到的解决方法有:卫语句,策略模式,状态模式。本文讲述的是通过策略模式来解决多重判断if-else语句问题。
一、多重判断if-else代码
我们通过支付接口的例子来讲述。代码如下:
1、Controller层
@RestController public class PayController { @Autowired private PayService payService; @RequestMapping("/pay") public String pay(String type, String amount){ return payService.pay(type, amount); } }
2、Service层
public interface PayService { /** * 支付接口 * @param type 支付类型 * @param amount 支付金额 * @return */ String pay(String type, String amount); } @Service public class PayServiceImpl implements PayService{ private static String MSG = "使用 %s ,消费了 %s 元"; @Override public String pay(String type, String amount) { if (PayEnum.ALI_PAY.getType().equals(type)){ // 支付宝支付 return String.format(MSG, PayEnum.ALI_PAY.getDescription(), amount); } else if (PayEnum.WECHAT_PAY.getType().equals(type)) { // 微信支付 return String.format(MSG, PayEnum.WECHAT_PAY.getDescription(), amount); } else if (PayEnum.UNION_PAY.getType().equals(type)) { // 银联支付 return String.format(MSG, PayEnum.UNION_PAY.getDescription(), amount); } return "输入的支付类型错误!"; } }
3、Enum枚举类
public enum PayEnum { ALI_PAY("ali", "支付宝支付"), WECHAT_PAY("wechat", "微信支付"), UNION_PAY("union", "银联支付"); private String type; private String description; PayEnum(String type, String description) { this.type = type; this.description = description; } public String getType() { return type; } public String getDescription() { return description; } }
当需要增加一个信用卡支付时,需要修改原来的代码,这样就违法了“开闭原则”。
二、策略模式代码
主要是Service层代码有所改变。
1、Service层
public interface PayService { /** * 支付接口 * @param type 支付类型 * @param amount 支付金额 * @return */ String pay(String type, String amount); } @Service public class PayServiceImpl implements PayService{ private static String MSG = "使用 %s ,消费了 %s 元"; @Override public String pay(String type, String amount) { PayStrategy payStrategy = PayStrategyFactory.getPayStrategy(type); if (payStrategy == null){ return "输入的支付类型错误!"; } return payStrategy.pay(type, amount); } }
2、对多重判断if-else语句的改造
public interface PayStrategy { String MSG = "使用 %s ,消费了 %s 元"; String pay(String type, String amount); } @Component("aliPayStrategy") public class AliPayStrategyImpl implements PayStrategy{ @Override public String pay(String type, String amount) { return String.format(MSG, PayEnum.ALI_PAY.getDescription(), amount); } } @Component("wechatPayStrategy") public class WechatPayStrategyImpl implements PayStrategy{ @Override public String pay(String type, String amount) { return String.format(MSG, PayEnum.WECHAT_PAY.getDescription(), amount); } } @Component("unionPayStrategy") public class UnionPayStrategyImpl implements PayStrategy{ @Override public String pay(String type, String amount) { return String.format(MSG, PayEnum.UNION_PAY.getDescription(), amount); } }
3、修改后的枚举类
public enum PayEnum { ALI_PAY("ali", "支付宝支付", "aliPayStrategy"), WECHAT_PAY("wechat", "微信支付", "wechatPayStrategy"), UNION_PAY("union", "银联支付", "unionPayStrategy"); private String type; private String description; private String beanName; PayEnum(String type, String description, String beanName) { this.type = type; this.description = description; this.beanName = beanName; } public String getType() { return type; } public String getDescription() { return description; } public String getBeanName() { return beanName; } public static PayEnum getByType(String type){ if (type == null){ return null; } for (PayEnum payEnum:values() ) { if (payEnum.getType().equals(type)){ return payEnum; } } return null; } }
4、通过以下工具类,能够获取到PayStrategy实现类关联。
public class SpringContextUtil implements ApplicationContextAware { /** * 上下文对象实例 */ private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringContextUtil.applicationContext = applicationContext; } public static ApplicationContext getApplicationContext(){ return applicationContext; } public static <T> T getBean(String name){ return (T)getApplicationContext().getBean(name); } public static <T> T getBean(String name, Class<T> clazz){ return getApplicationContext().getBean(name, clazz); } }
5、Service调用PayStrategy的工厂类,返回PayStrategy的实现类
public class PayStrategyFactory { /** * 根据type获取对应PayStrategy实现类 * @param type * @return */ public static PayStrategy getPayStrategy(String type){ PayEnum payEnum = PayEnum.getByType(type); if (payEnum == null){ return null; } return SpringContextUtil.getBean(payEnum.getBeanName(), PayStrategy.class); } }
通过这样的改造,当我们增加一个信用卡支付时,只需要添加一个PayStrategy的实现类,并在PayEnum枚举类添加一个信用卡支付的成员就可以了。
原文:https://www.cnblogs.com/chenrencun/p/13634268.html