概述
利用多态,使得同一行为(方法)在不同场景下有不同的实现,并且将使用与实现分离。
优点:
-
能够解决if-else过多问题
-
开闭原则,有新的策略时,只需要新建具体策略类即可
缺点:
- 策略类过多
使用场景:
- 需要动态地在几种算法中选择一种
传统策略模式
角色
上下文类(Context):组合抽象策略类,注入具体策略类,实现调用不同策略实现
抽象策略类(Strategy):定义公共接口
具体策略类(ConcreteStrategy):实现抽象策略
类图
策略模式代码
上下文类
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
/**
* 调用策略类
*/
public void strategyMethod() {
strategy.strategyMethod();
}
public Strategy getStrategy() {
return strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
}
抽象策略类
public interface Strategy {
void strategyMethod();
}
具体策略类A
public class ConcreteStrategyA implements Strategy {
@Override
public void strategyMethod() {
System.out.println("ConcreteStrategyA...");
}
}
具体策略类B
public class ConcreteStrategyB implements Strategy {
@Override
public void strategyMethod() {
System.out.println("ConcreteStrategyB...");
}
}
客户端
public class Client {
public static void main(String[] args) {
Context context = new Context(new ConcreteStrategyA());
context.strategyMethod();
}
}
// 输出:ConcreteStrategyA...
具体策略类自动生成
上面存在的问题:Client需要显示去创建具体策略类,需要解耦,可以利用 Spring IOC,把上下文类替换为策略工厂类,然后具体策略类加上@Component注解
类图
策略模式 (2).png代码
策略工厂类
@Component
public class StrategyFactory {
/**
* spring 会将所有Strategy类型注入进map
* key就是bean的名称,value就是Strategy
*/
@Autowired
private Map<String, Strategy> strategyMap;
/**
* 调用策略类
*/
public void strategyMethod(String key) {
Strategy strategy = strategyMap.get(key);
if (strategy != null) {
strategy.strategyMethod();
}
}
}
具体策略类A
/**
* 具体策略类A
*/
@Component(value = "ConcreteStrategyA")
public class ConcreteStrategyA implements Strategy {
@Override
public void strategyMethod() {
System.out.println("ConcreteStrategyA...");
}
}
Map + Lambda表达式实现策略模式
上面存在的问题:随着策略的增加,策略类数量势必增多,管理和维护难度也随之增加。另外,无法从宏观层面看到所有的策略实现类。
策略选择器
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
@Service
public class StrategySelector {
@Autowired
private StrategyService strategyService;
private Map<String, Function<String, String>> strategyMap = new HashMap<>();
@PostConstruct
public void initMap() {
strategyMap.put("f1", o -> strategyService.f1());
strategyMap.put("f2", o -> strategyService.f2());
strategyMap.put("f3", o -> strategyService.f3());
}
/**
* 根据type获取对应策略
*/
public String getResult(String type) {
Function<String, String> function = strategyMap.get(type);
if (function != null) {
// 执行表达式获得对应结果
return function.apply(type);
}
return null;
}
}
策略实现类
@Service
class StrategyService {
public String f1() {
return "f1";
}
public String f2() {
return "f2";
}
public String f3() {
return "f3";
}
}
利用Map+lambda实现策略模式,Map的value可以是Java 8 内置四大函数式接口
网友评论