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

策略模式

描述

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

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

基本使用

  • 定义策略接口
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");
    }
}

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

相关推荐
老蒋每日coding17 小时前
AI智能体设计模式系列(一)—— 提示词链
设计模式·ai编程
sxlishaobin20 小时前
设计模式之模板方法模式
设计模式·模板方法模式
le16161620 小时前
设计模式之单例模式
单例模式·设计模式
Knight_AL20 小时前
从单例模式说起:Java 常见设计模式的理解与实践
java·单例模式·设计模式
Engineer邓祥浩20 小时前
设计模式学习(10) 23-8 装饰者模式
python·学习·设计模式
老蒋每日coding21 小时前
基于LangGraph的AI Agent并行化设计模式详解
设计模式·ai编程
GISer_Jing21 小时前
AI学习资源总结:免费开放,入门至深入,持续更新
人工智能·学习·设计模式·prompt·aigc
Geoking.1 天前
【设计模式】策略模式(Strategy)详解:把 if-else 变成可切换的算法
java·设计模式·策略模式
老蒋每日coding1 天前
AI智能体设计模式系列(二)—— 路由模式
人工智能·设计模式
老蒋每日coding1 天前
AI智能体设计模式系列(四)—— 反思模式
设计模式