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

策略模式

描述

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

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

基本使用

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

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

相关推荐
学习机器不会机器学习4 小时前
深入浅出JavaScript常见设计模式:从原理到实战(2)
开发语言·javascript·设计模式
碎梦归途4 小时前
23种设计模式-行为型模式之命令模式(Java版本)
java·开发语言·jvm·设计模式·命令模式·行为型模式
〆、风神7 小时前
从零搭建高可用分布式限流组件:设计模式与Redis令牌桶实践
redis·分布式·设计模式
摘星编程8 小时前
并发设计模式实战系列(8):Active Object
设计模式·并发编程
碎梦归途19 小时前
23种设计模式-行为型模式之策略模式(Java版本)
java·开发语言·jvm·设计模式·策略模式·行为型模式
Java致死1 天前
单例设计模式
java·单例模式·设计模式
麓殇⊙1 天前
设计模式--桥接模式详解
设计模式·桥接模式
学习机器不会机器学习1 天前
深入浅出JavaScript常见设计模式:从原理到实战(1)
开发语言·javascript·设计模式
ApeAssistant1 天前
Spring + 设计模式 (二十) 行为型 - 中介者模式
spring·设计模式