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

策略模式

描述

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

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

基本使用

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

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

相关推荐
Arva .8 小时前
责任链设计模式->规则树
设计模式
WKP94188 小时前
命令设计模式
设计模式
lapiii35812 小时前
[智能体设计模式] 第4章:反思(Reflection)
人工智能·python·设计模式
颜酱1 天前
理解编程范式(前端角度)
设计模式
将编程培养成爱好1 天前
C++ 设计模式《账本事故:当备份被删光那天》
开发语言·c++·设计模式·备忘录模式
FogLetter1 天前
设计模式奇幻漂流:从单例孤岛到工厂流水线
前端·设计模式
guangzan1 天前
常用设计模式:代理模式
设计模式
西幻凌云1 天前
认识设计模式——单例模式
c++·单例模式·设计模式·线程安全·饿汉和懒汉
爱吃烤鸡翅的酸菜鱼1 天前
【Java】基于策略模式 + 工厂模式多设计模式下:重构租房系统核心之城市房源列表缓存与高性能筛选
java·redis·后端·缓存·设计模式·重构·策略模式
在未来等你2 天前
AI Agent设计模式 Day 5:Reflexion模式:自我反思与持续改进
设计模式·llm·react·ai agent·plan-and-execute