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

策略模式

描述

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

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

基本使用

  • 定义策略接口
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 小时前
游戏设计模式 - 子类沙箱
游戏·unity·设计模式
漫谈网络4 小时前
MVC与MVP设计模式对比详解
设计模式·mvc
蔡蓝4 小时前
设计模式-观察着模式
java·开发语言·设计模式
哆啦A梦的口袋呀6 小时前
基于Python学习《Head First设计模式》第六章 命令模式
python·学习·设计模式
半路下车8 小时前
【Harmony OS 5】HarmonyOS应用测试指南
设计模式·harmonyos
周某某~8 小时前
一.设计模式的基本概念
设计模式
on the way 1238 小时前
行为型设计模式之Interpreter(解释器)
设计模式
cui_hao_nan8 小时前
设计模式——模板方法
java·设计模式
在未来等你8 小时前
Java并发编程实战 Day 11:并发设计模式
java·设计模式·多线程·并发编程·threadlocal·生产者消费者·读写锁
牛奶咖啡139 小时前
学习设计模式《十二》——命令模式
学习·设计模式·命令模式·队列请求·宏命令·可撤销恢复操作·参数化配置