策略模式
定义一个算法家族,分别封装,让他们互相之间替换,解决if…else和switch语句
策略模式优缺点
优点:上下文和具体策略是松耦合关系
缺点: 1. 客户端必须知道有哪些策略,并且自行决定使用哪种策略
2. 增加许多类,增加维护难度
spring中的使用策略模式
方式一:使用注解
详见代码strategy模块 com.su.example.annotation.demo
支付注解-只要有这个注解则代表他是该策略
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PayStrategyType {
PayTypeEnum value();
}
支付类型枚举
public enum PayTypeEnum {
ALI_PAY(1,"阿里支付"),
WEIXIN_PAY(2,"微信支付"),
UNION_PAY(3,"银联"),
;
private Integer code;
private String msg;
PayTypeEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
}
扫描所有支付注解,将支付service放入一个map
@Component
@Order
public class HandlerPayMoneyStrategyProcessor implements ApplicationContextAware {
/**
* 获取所有的策略 加入HandlerOrderContext属性中
* @param applicationContext
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//获取所有策略注解的Bean
Map<String, Object> beanMap = applicationContext.getBeansWithAnnotation(PayStrategyType.class);
PayMoneyStrategyContext bean = applicationContext.getBean(PayMoneyStrategyContext.class);
beanMap.forEach((k,v)->{
PayTypeEnum type = AopUtils.getTargetClass(v).getAnnotation(PayStrategyType.class).value();
//将class加入map中,type作为key
bean.getPayMoneyStrategyMap().put(type,(IPayMoneyStrategy) v);
});
}
}
策略的接口
public interface IPayMoneyStrategy {
/**
* 付钱
* @param money
*/
void payMoney(BigDecimal money);
}
策略的实现-阿里
@Component
@PayStrategyType(PayTypeEnum.ALI_PAY)
public class AliPayStrategyImpl implements IPayMoneyStrategy {
@Override
public void payMoney(BigDecimal money) {
System.out.println("我是阿里支付生成金额为:"+ money +"流水开始支付");
}
}
策略的实现-微信
@Component
@PayStrategyType(PayTypeEnum.WEIXIN_PAY)
public class WeixinPayStrategyImpl implements IPayMoneyStrategy {
@Override
public void payMoney(BigDecimal money) {
System.out.println("我是微信支付生成金额为:"+ money +"流水开始支付");
}
}
方式二:使用统一的config类注入
注入类
public class MapHandlerPayMoneyStrategyProcessor {
@Resource
IMapPayMoneyStrategy mapAliPayStrategyImpl;
@Resource
IMapPayMoneyStrategy mapUnionPayStrategyImpl;
@Resource
IMapPayMoneyStrategy mapWeixinPayStrategyImpl;
@Bean("payMoneyStrategyMap")
public Map<PayTypeEnum, IMapPayMoneyStrategy> createPayMoneyStrategyMap() throws BeansException {
Map<PayTypeEnum, IMapPayMoneyStrategy> payTypeEnumIMapPayMoneyStrategyHashMap = new HashMap(8);
payTypeEnumIMapPayMoneyStrategyHashMap.put(PayTypeEnum.ALI_PAY,mapAliPayStrategyImpl);
payTypeEnumIMapPayMoneyStrategyHashMap.put(PayTypeEnum.UNION_PAY,mapUnionPayStrategyImpl);
payTypeEnumIMapPayMoneyStrategyHashMap.put(PayTypeEnum.WEIXIN_PAY,mapWeixinPayStrategyImpl);
return payTypeEnumIMapPayMoneyStrategyHashMap;
}
}
方式三:工厂策略模式
工厂
@Component
public class FactoryPayMoneyStrategyContext {
/**
* 对外统一暴露服务
*/
public void strategyManage(PayTypeEnum payType, BigDecimal money) {
IFactoryPayMoneyStrategy iFactoryPayMoneyStrategy;
switch (payType){
case ALI_PAY:
iFactoryPayMoneyStrategy = new FactoryAliPayStrategyImpl();
break;
case WEIXIN_PAY:
iFactoryPayMoneyStrategy = new FactoryWeixinPayStrategyImpl();
break;
case UNION_PAY:
iFactoryPayMoneyStrategy = new FactoryUnionPayStrategyImpl();
break;
default: throw new RuntimeException("找不到的服务");
}
iFactoryPayMoneyStrategy.payMoney(money);
}
}
其他大同小异
调用:
ApplicationContext applicationContext = ApplicationHolder.getApplicationContext();
PayMoneyStrategyContext bean = applicationContext.getBean(PayMoneyStrategyContext.class);
System.out.println("注解模式---------------------------");
bean.strategyManage(PayTypeEnum.ALI_PAY, BigDecimal.TEN);
bean.strategyManage(PayTypeEnum.WEIXIN_PAY, BigDecimal.TEN);
bean.strategyManage(PayTypeEnum.UNION_PAY, BigDecimal.TEN);
System.out.println("map模式---------------------------");
MapPayMoneyStrategyContext mapBean = applicationContext.getBean(MapPayMoneyStrategyContext.class);
mapBean.strategyManage(PayTypeEnum.ALI_PAY, BigDecimal.TEN);
mapBean.strategyManage(PayTypeEnum.WEIXIN_PAY, BigDecimal.TEN);
mapBean.strategyManage(PayTypeEnum.UNION_PAY, BigDecimal.TEN);
System.out.println("工厂策略模式---------------------------");
FactoryPayMoneyStrategyContext factoryBean = applicationContext.getBean(FactoryPayMoneyStrategyContext.class);
factoryBean.strategyManage(PayTypeEnum.ALI_PAY, BigDecimal.TEN);
factoryBean.strategyManage(PayTypeEnum.WEIXIN_PAY, BigDecimal.TEN);
factoryBean.strategyManage(PayTypeEnum.UNION_PAY, BigDecimal.TEN);
PS: git代码