策略模式是让策略的实现与策略的使用解耦,在我们日常的开发中,经常用来重构和优化if-else和switch语句。当然,策略模式并不是为了取代if-else和switch语句而生的,这里好多人有一个误区,它的思想是接口的一组实现可以相互替换,让使用和实现解耦。
策略的使用分为2种,一种是有状态的,每个if-else分支的策略使用都需要new一个新的策略对象;一种是无状态的,每个if-else分支的策略使用都用一个公共的策略对象。
策略类的一个demo如下:
代码语言:javascript复制public interface Strategy {
void doStrategy();
}
public class StrategyA implements Strategy {
private Logger logger = LoggerFactory.getLogger(getClass());
public void doStrategy() {
logger.info("doStrategy StrategyA");
}
}
public class StrategyB implements Strategy{
private Logger logger = LoggerFactory.getLogger(getClass());
public void doStrategy() {
logger.info("doStrategy StrategyB");
}
}
有状态的策略模式使用:
代码语言:javascript复制public class StrategyStatefulFactory {
public static Strategy getStatefulStrategy(String type){
if (StringUtils.isEmpty(type)){
throw new IllegalArgumentException("type must be not null");
}
if(StringUtils.pathEquals(type, "strategyA")){
return new StrategyA();
}else if(StringUtils.pathEquals(type, "strategyB")){
return new StrategyB();
}else{
return null;
}
}
}
无状态的策略模式使用
代码语言:javascript复制public class StrategyNonStatefulFactory {
private static Map<String, Strategy> strategyMap = new HashMap<>(3);
static {
strategyMap.put("strategyA", new StrategyA());
strategyMap.put("strategyB", new StrategyB());
}
public static Strategy getStrategy(String type){
if (StringUtils.isEmpty(type)){
throw new IllegalArgumentException("type must be not null");
}
return strategyMap.get(type);
}
}
上面的策略工厂,当我们新加入一个策略类时,都需要修改工厂类,这有点不符合开闭原则,那怎么来处理呢?一种方式是在配置文件中增加配置,工厂初始化的时候读配置文件来初始化工厂中map,第二种方式是通过注解来标注策略类,使用java反射机制来初始化工厂中map。这里我给出一个第二种方式实现的demo
代码语言:javascript复制@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Strategic {
String value();
}
public interface AnnotationStrategy {
void doStrategy();
}
@Strategic(value = "strategyA")
public class AnnotationStrategyA implements AnnotationStrategy{
private Logger logger = LoggerFactory.getLogger(getClass());
public void doStrategy(){
logger.info("doStrategy AnnotationStrategyA");
}
}
@Strategic(value = "strategyB")
public class AnnotationStrategyB implements AnnotationStrategy{
private Logger logger = LoggerFactory.getLogger(getClass());
public void doStrategy(){
logger.info("doStrategy AnnotationStrategyB");
}
}
工厂类代码如下:
代码语言:javascript复制public class AnnotationStrategyFactory {
private static Logger logger = LoggerFactory.getLogger(AnnotationStrategyFactory.class);
static Map<String, AnnotationStrategy> map = new HashMap<>(3);
static {
File classPath = new File("./target/classes/design/behavioral/strategy");
String package = "design.behavioral.strategy";
if (classPath.exists()) {
for (File file : classPath.listFiles()){
String fileName = file.getName();
if (fileName.endsWith(".class")) {
fileName = fileName.replace(".class", "");
try {
Class<?> classZ = Class.forName(package "." fileName);
if (classZ.isAnnotationPresent(Strategic.class)){
map.put(classZ.getAnnotation(Strategic.class).value(), (AnnotationStrategy)classZ.newInstance());
}
} catch (Exception e) {
logger.error("exception:", e);
}
}
}
}
}
public static AnnotationStrategy getAnnotationStrategy(String type) {
return map.get(type);
}
}
源码地址:
https://github.com/jinjunzhu/design-pattern.git