引言
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
经典的商城打折生活用例,这种场景最适合用策略模式,客户将自己的身份告诉商城,商城根据客户的类型给予不同的优惠策略,普通用户不打折,会员8折,内部员工三折。如果不用设计模式用if...else语句实现起来也就几行代码的事情,不过这种实现方式看起来不太优雅,没有体现设计思维,所以我们尝试用Spring机制来实现策略模式吧。
我们来看类图。
image.png
IDiscountStrategy是折扣接口
*StrategyImpl这些类实现的是不同的客户类型使用的不同的折扣策略。
StrateType是自定义折扣类型注解。
StrategyHandlerComponent这个类是Spring的组件类,通过它获取所有的折扣类,将这些折扣类存放在一个线程安全的HashMap中,key存储的是DiscountEnum枚举中的name();
一句话表达就是将折扣类和折扣类型关键字建立起mapping隐射。
public enum DiscountEnum {
/**
* 普通客户
*/
NOMARL,
/**
* 会员
*/
MEMBER,
EMPLOYEE;
}
最后就是客户调用步骤
@Autowired
StrategyHandlerComponent strategyHandlerComponet;
@GetMapping("/strategy")
public String strategy(String strategy) {
ConcurrentHashMap map=strategyHandlerComponet.getDiscountStrategyConcurrentHashMap();
if(map.keySet().contains(strategy)){
return "外星人不能享受折扣优惠";
}
return map.get(strategy).discount();
}
核心代码StrategyHandlerComponent
package com.sgm.ossp.order.strategy;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import java.util.concurrent.ConcurrentHashMap;
@Component
public class StrategyHandlerComponent implements BeanPostProcessor {
private ConcurrentHashMap discountStrategyConcurrentHashMap=new ConcurrentHashMap<>();
public ConcurrentHashMap getDiscountStrategyConcurrentHashMap() {
return discountStrategyConcurrentHashMap;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
Class aClass=bean.getClass();
if(aClass.isAnnotationPresent(StrateType.class)&&isInstanceOfDiscountStrategy(aClass)){
StrateType strateType= (StrateType) aClass.getAnnotation(StrateType.class);
System.out.println("输出bean......"+bean.getClass().getName());
discountStrategyConcurrentHashMap.put(strateType.value().name(),(IDiscountStrategy) bean);
}
return bean;
}
//类似于InitializingBean.afterPropertiesSet()
//这里面获取所有的折扣实现类
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
private boolean isInstanceOfDiscountStrategy( Class aClass){
try {
return (aClass.newInstance() instanceof IDiscountStrategy);
} catch (Exception e) {
return false;
}
}
}
部署到Tomcat之后以get请求示例:{protocol}://{ip}:{port}/strategy?strategy={枚举类的name()}