设计模式简述(十二)策略模式

策略模式

描述

定义一组策略,并将其封装起来到一个策略上下文中。

由调用者决定应该使用哪种策略,并且可以动态替换

基本使用

  • 定义策略接口
java 复制代码
public interface IStrategy {
    void action();
}
  • 声明具体策略类
java 复制代码
public class StrategyA implements IStrategy {
    @Override
    public void action() {
        System.out.println("策略A.....");
    }
}


public class StrategyB implements IStrategy {
    @Override
    public void action() {
        System.out.println("策略B.....");
    }
}
  • 定义策略上下文(调用方通过上下文发起策略调用)
java 复制代码
public class StrategyContext {
    private IStrategy strategy;

    public StrategyContext(IStrategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(IStrategy strategy) {
        this.strategy = strategy;
    }

    public void doAction() {
        strategy.action();
    }
}

使用

调用方选择一个策略,并创建策略上下文 发起调用

java 复制代码
public class Sample {
    public static void main(String[] args) {
        IStrategy strategyA = new StrategyA();
        // 初始化时持有策略A
        StrategyContext context = new StrategyContext(strategyA);
        context.doAction();
        System.out.println("===== 替换策略 ====");
        // 动态替换为策略B
        IStrategy strategyB = new StrategyB();
        context.setStrategy(strategyB);
        context.doAction();
    }
}

传统策略模式的缺陷以及规避方法

和工厂模式中子工厂数量过多的问题一致。当策略数量变多时,会对调用方不够友好,调用方并不想了解具体策略的实现

我们可以参考工厂模式的处理方式:引入一个协调类对所有策略进行管理

  • 定义一个协调类(将所有策略管理起来,具体方案多种多样)
java 复制代码
public final class StrategyFactory {
    private static Map<String, IStrategy> strategyMap = new HashMap<>();

    static {
        strategyMap.put("A", new StrategyA());
        strategyMap.put("B", new StrategyB());
    }

    public static IStrategy getInstance(String code) {
        return strategyMap.get(code);
    }
}
  • 具体策略的选择放到策略上下文中,根据调用方传入的标识选择对应的策略
java 复制代码
public class StrategyContextV2 {
    private IStrategy strategy;

    public StrategyContextV2(String code) {
        this.strategy = StrategyFactory.getInstance(code);
    }

    public void setStrategy(String code) {
        this.strategy = StrategyFactory.getInstance(code);
    }

    public void doAction() {
        strategy.action();
    }
}
  • 使用(调用方只需传入策略标识,可以调用对应策略。调用方对具体策略无感知)
java 复制代码
public class SampleV2 {
    public static void main(String[] args) {
        StrategyContextV2 contextV2 = new StrategyContextV2("A");
        contextV2.doAction();
        System.out.println("===== 替换策略 ====");
        contextV2.setStrategy("B");
        contextV2.doAction();
    }
}

枚举策略

描述

基于以上传统策略中使用协调类来规避具体策略对调用方的影响考虑。

总的来说,这就是一种表驱动的思想。将一些控制逻辑抽离为一些特定的数据结构(不限于数组字典外部配置文件等等)

Java中的枚举就是一种自带表驱动属性的数据类型

基本使用

  • 定义策略枚举
java 复制代码
public enum StrategyEnum {
    A("A策略") {
        @Override
        public void action() {
            System.out.println("调用策略A.....");
        }
    },
    B("B策略") {
        @Override
        public void action() {
            System.out.println("调用策略B.....");
        }
    },
    ;

    /**
     * 策略描述
     */
    private final String desc;

    StrategyEnum(String desc) {
        this.desc = desc;
    }

    public abstract void action();
}
  • 定义策略枚举上下文
java 复制代码
public class StrategyContext {
    public static void doAction(String code) {
        StrategyEnum.valueOf(code).action();
    }
}

使用

同样只需传入策略标识即可

java 复制代码
public class Sample {
    public static void main(String[] args) {
        StrategyContext.doAction("A");
        StrategyContext.doAction("B");
    }
}

可以看到,使用枚举实现似乎更加简单

相关推荐
vker5 小时前
第 1 天:单例模式(Singleton Pattern)—— 创建型模式
java·设计模式
晨米酱1 天前
JavaScript 中"对象即函数"设计模式
前端·设计模式
数据智能老司机1 天前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机1 天前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机1 天前
精通 Python 设计模式——性能模式
python·设计模式·架构
使一颗心免于哀伤1 天前
《设计模式之禅》笔记摘录 - 21.状态模式
笔记·设计模式
数据智能老司机2 天前
精通 Python 设计模式——创建型设计模式
python·设计模式·架构
数据智能老司机2 天前
精通 Python 设计模式——SOLID 原则
python·设计模式·架构
烛阴2 天前
【TS 设计模式完全指南】懒加载、缓存与权限控制:代理模式在 TypeScript 中的三大妙用
javascript·设计模式·typescript