策略模式

概述

利用多态,使得同一行为(方法)在不同场景下有不同的实现,并且将使用与实现分离。

优点:

  • 能够解决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 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> 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 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 内置四大函数式接口

你可能感兴趣的:(策略模式)