策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。比如每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法。–维基百科
在项目中时常会用到策略模式的场景,比如业务中需要支付,但是有多个支付渠道,那如何对上层业务暴露"统一口径"(接口)呢,下面结合代码说明,
首先定义支付接口:
public interface Pay{
// 具体支付业务逻辑
public void toPay();
// 支付类型
public Integer payType();
}
AliPay:
public class AliPay implements Pay{
public void toPay(){
...
}
public Integer payType(){
// 返回支付类型枚举
return 1;
}
}
WxPay:
public class WxPay implements Pay{
public void toPay(){
...
}
public Integer payType(){
// 返回支付类型枚举
return 2;
}
}
不同的实现已经好了,需要在上层业务中传入不同的支付类型,调用具体的实现,结合在Spring项目中使用方式:
@Component
public class PayTypeUtil implements InitializingBean{
@Autowired
private List<Pay> payList;
private static final Map<Integer,Pay> payMap = Maps.newHashMap();
@Override
public void afterPropertiesSet() throws Exception {
for (Pay pay : payList) {
payMap.put(pay.payType(),pay);
}
}
public Pay getPayService(Integer payType){
return payMap.get(payType);
}
public static void putService(Pay pay){
payMap.put(pay.payType(),pay);
}
}
直接使用PayTypeUtil
的getPayService方法传入不同的支付类型便可得到具体的实现,上面借助了Spring中的InitializingBean
接口实现了在bean初始化时,加载Pay
所有的实现类(InitializingBean可参考文章https://blog.youkuaiyun.com/BAT_os/article/details/81844985),难道只有这种方法才可以实现么,当然不是,下面再介绍两种方法:
- SPI
SPI的用法参考文章https://blog.youkuaiyun.com/BAT_os/article/details/83042569,下面用代码说明:
1. 在META-INF/services中添加文件com.xxx.BaseApplication,并写入com.xxx.AliPay,com.xxx.WxPay
2. 获取Pay所有实现,并注册
ServiceLoader<Pay> payLoader = ServiceLoader.load(Pay.class);
for(Pay pay:payLoader){
PayTypeUtil.putService(pay);
}
- @PostConstruct
Java EE5引入了@PostConstruct
(与之对应的是@PreDestroy),作用于Servlet生命周期的注解,实现Bean初始化之前的自定义操作,关于@PostConstruct
可参考https://docs.oracle.com/javaee/5/api/javax/annotation/PostConstruct.html,具体代码:
public class AliPay implements Pay{
@PostConstruct
public void init(){
PayTypeUtil.putService(this);
}
public void toPay(){
...
}
public Integer payType(){
// 返回支付类型枚举
return 1;
}
}
public class WxPay implements Pay{
@PostConstruct
public void init(){
PayTypeUtil.putService(this);
}
public void toPay(){
...
}
public Integer payType(){
// 返回支付类型枚举
return 2;
}
}
以上简单说明策略模式的用法,根据实际的业务场景结合使用.