策略模式终极解决方案之策略机

我们在开发时经常会遇到一堆的if else …, 或者switch, 比如我们常见的全局异常处理等, 像类似这种很多if else 或者多场景模式下, 策略模式是非常受欢迎的一种设计模式, 然而, 一个好的策略模式却不是那么容易写出来.

我在工作中也因为写烦了switch,if else 觉得很不优雅, 因此,我考虑是否有一套统一的解决方案呢?

思考我问题的初衷, 在什么策略下, 满足什么条件执行什么动作, 返回什么值, 这就是策略模式需要解决的核心问题, 大眼一看好似有点类似状态机? 然而它并不是状态机, 状态机是比较笨重, 而策略机应该是足够轻量的.

我们再来看核心问题,关于什么策略,满足什么条件执行什么动作,返回什么值, 是一个明显的dsl语法, 因此, 我的基本语法糖已确立: strategy.of().when().perform()或者strategy.of().perform(), 因为有时我们并不需要条件, 仅仅策略即可.

我们要实现上述语法糖, 就得设计一套规则, 使其可以满足dsl, 并且是合理的, 如此, 基本定义已确定, 如下:

/**
 * {@link StrategyMachineBuilder}
 * @param <S> strategy
 * @param <C> context
 * @param <R> result
 */
public interface StrategyMachineBuilder<S,C,R> {

    Of<S,C,R> of(S s);

    StrategyMachine<S,C,R> build(String id);
}
/**
 * {@link Of}
 * @param <S> strategy
 * @param <C> context
 * @param <R> result
 */
public interface Of<S,C,R> {
    When<S,C,R> when(Condition<S,C,R> condition);

    StrategyMachineBuilder<S,C,R> perform(Action<C,R> action);
}
/**
 * {@link When}
 * @param <S> strategy
 * @param <C> context
 * @param <R> result
 */
public interface When<S,C,R> {

    StrategyMachineBuilder<S,C,R> perform(Action<C,R> action);
}

/**
 * {@link Condition}
 * @param <S> strategy
 * @param <C> context
 * @param <R> result
 */
public interface Condition<S,C,R> {

    boolean isSatisfied(S s,C c);
}

/**
 * {@link Action}
 * @param <C> context
 * @param <R> result
 */
public interface Action<C,R> {
    R apply(C c);
}
/**
 * {@link Strategy}
 * @param <S> strategy
 * @param <C> context
 * @param <R> result
 */
public interface Strategy<S, C, R> {
    S strategy();
    Condition<S,C,R> condition();
    Action<C, R> action();

    Strategy<S,C,R> strategy(S s);
    Strategy<S,C,R> condition(Condition<S,C,R> condition);
    Strategy<S,C,R> action(Action<C,R> action);
}

/**
 * {@link StrategyMachine}
 * @param <S> strategy
 * @param <C> context
 * @param <R> result
 */
public interface StrategyMachine<S,C,R> {

    R apply(S s, C c);
}

如此: 架构已经构建完毕, 剩下的工作就很简单了, 实现此架构即可.

/**
 * {@link StrategyMachineBuilderImpl}
 * @param <S> strategy
 * @param <C> context
 * @param <R> result
 */
class StrategyMachineBuilderImpl<S,C,R> implements StrategyMachineBuilder<S,C,R>{
    private final Map<S, List<Strategy<S,C,R>>> map = new ConcurrentHashMap<>();


    @Override
    public Of<S, C, R> of(S s) {
        map.computeIfAbsent(s, k -> new ArrayList<>());
        Strategy<S,C,R> strategy = new StrategyImpl();
        map.get(s).add(strategy);
        return new OfImpl(strategy);
    }

    @Override
    public StrategyMachine<S, C, R> build(String id) {
        StrategyMachineImpl<S, C, R> machine = new StrategyMachineImpl<>(map);
        StrategyCache.put(id, machine);
        return machine;
    }

    public class OfImpl implements Of<S,C,R>{
        private final Strategy<S,C,R> strategy;
        OfImpl(Strategy<S,C,R> strategy){
            this.strategy = strategy;
        }

        @Override
        public When<S, C, R> when(Condition<S,C,R> condition) {
            this.strategy.condition(condition);
            return new WhenImpl(strategy);
        }

        @Override
        public StrategyMachineBuilder<S, C, R> perform(Action<C, R> action) {
            this.strategy.action(action);
            return StrategyMachineBuilderImpl.this;
        }
    }

    public class WhenImpl implements When<S,C,R> {

        private final Strategy<S,C,R> strategy;
        WhenImpl(Strategy<S,C,R> strategy){
            this.strategy = strategy;
        }

        @Override
        public StrategyMachineBuilder<S, C, R> perform(Action<C, R> action) {
            this.strategy.action(action);
            return StrategyMachineBuilderImpl.this;
        }
    }

    public class StrategyImpl implements Strategy<S, C, R> {
        private S strategy;
        private Condition<S,C,R> condition;
        private Action<C, R> action;


        @Override
        public S strategy() {
            return this.strategy;
        }

        @Override
        public Condition<S,C,R> condition() {
            return this.condition;
        }

        @Override
        public Action<C, R> action() {
            return this.action;
        }

        @Override
        public Strategy<S, C, R> strategy(S s) {
            this.strategy = s;
            return this;
        }

        @Override
        public Strategy<S, C, R> condition(Condition<S,C,R> condition) {
            this.condition = condition;
            return this;
        }

        @Override
        public Strategy<S, C, R> action(Action<C, R> action) {
            this.action = action;
            return this;
        }
    }
}
/**
 * Strategy Machine Impl
 * @param <S> strategy
 * @param <C> context
 * @param <R> result
 */
class StrategyMachineImpl<S,C,R> implements StrategyMachine<S,C,R> {

    private final Map<S, List<Strategy<S,C,R>>> map;

    public StrategyMachineImpl(Map<S, List<Strategy<S,C,R>>> map){
        this.map = map;
    }


    @Override
    public R apply(S s, C c) {
        List<Strategy<S, C, R>> strategies = map.get(s);
        if (strategies==null||strategies.isEmpty()){
            throw new RuntimeException("no strategy found for "+s);
        }

        for (Strategy<S, C, R> strategy : strategies) {
            // 如果没有condition,直接执行action
            if (strategy.condition()==null) {
                return strategy.action().apply(c);
            }
            // 如果有condition,先判断是否满足condition,满足则执行action
            if (strategy.condition().isSatisfied(s,c)){
                return strategy.action().apply(c);
            }
        }
        // 未发现策略关于s的condition
        throw new RuntimeException("no strategy found of met condition for "+s);
    }
}
/**
 * Strategy Machine Factory
 */
public class StrategyMachineFactory {

    public static <S,C,R> StrategyMachineBuilder<S,C,R> create() {
        return new StrategyMachineBuilderImpl<>();
    }

    public static <S,C,R> StrategyMachine<S,C,R> get(String id) {
        return (StrategyMachine<S, C, R>) StrategyCache.get(id);
    }
}
/**
 * {@link StrategyCache}
 */
class StrategyCache {

    private static final Map<String,StrategyMachine<?,?,?>> CACHE = new java.util.concurrent.ConcurrentHashMap<>();

    public static void put(String id, StrategyMachine<?,?,?> machine) {
        CACHE.put(id, machine);
    }

    public static StrategyMachine<?,?,?> get(String id) {
        return CACHE.get(id);
    }
}

如此, 策略机已实现完毕. 下面给出两种场景例子
一. 不同年龄吃不同分量的药
Example:
Under the age of 12, take 20 milligrams of medication per day;
12-18 years old, taking 30 milligrams a day
18-30 years old, taking 40 milligrams a day
30-50 years old, taking 45 milligrams a day
Eating 42 milligrams for those over 50 years old

class MedicineStrategy {
        private static StrategyMachine<String, MedicineContext, Void> strategy;

        static {
            StrategyMachineBuilder<String, MedicineContext, Void> machineBuilder = StrategyMachineFactory.create();
            strategy = machineBuilder
                    .of("").when((s, c) -> c.age < 12).perform((c) -> {
                        System.out.println("Under the age of 12, take 20 milligrams of medication per day;");
                        return Void.TYPE.cast(null);
                    })
                    .of("").when((s, c) -> c.age >= 12 && c.age < 18).perform((c) -> {
                        System.out.println("12-18 years old, taking 30 milligrams a day");
                        return Void.TYPE.cast(null);
                    })
                    .of("").when((s, c) -> c.age >= 18 && c.age < 30).perform((c) -> {
                        System.out.println("18-30 years old, taking 40 milligrams a day");
                        return Void.TYPE.cast(null);
                    })
                    .of("").when((s, c) -> c.age >= 30 && c.age < 50).perform((c) -> {
                        System.out.println("30-50 years old, taking 45 milligrams a day");
                        return Void.TYPE.cast(null);
                    })
                    .of("").when((s, c) -> c.age >= 50).perform((c) -> {
                        System.out.println("Eating 42 milligrams for those over 50 years old");
                        return Void.TYPE.cast(null);
                    })
                    .build("medicine");
        }

        public static StrategyMachine<String, MedicineContext, Void> get() {
            // StrategyMachine<String, MedicineContext, Void> strategy = StrategyMachineFactory.get("medicine");
            return strategy;
        }

        @Data
        @AllArgsConstructor
        @NoArgsConstructor
        public static class MedicineContext {
            private int age;
        }

        public static void main(String[] args) {
            get().apply("", new MedicineContext(10));
        }

    }

二. 计算机

		StrategyMachineBuilder<String, StrategyContext, Number> machineBuilder = StrategyMachineFactory.create();
        machineBuilder.of("加法").perform(strategyContext -> strategyContext.a + strategyContext.b);
        machineBuilder.of("减法").perform(strategyContext -> strategyContext.a - strategyContext.b);
        machineBuilder.of("乘法").perform(strategyContext -> strategyContext.a * strategyContext.b);
        // 除法,当c==1时,忽略小数位, 当c==2时不忽略
        machineBuilder.of("除法").when((s, strategyContext) -> strategyContext.c == 1).perform(strategyContext -> strategyContext.a / strategyContext.b);
        machineBuilder.of("除法").when((s, strategyContext) -> strategyContext.c == 2).perform(strategyContext -> (strategyContext.a * 1.0d) / (strategyContext.b * 1.0d));
        StrategyMachine<String, StrategyContext, Number> strategyMachine = machineBuilder.build("test");
        // StrategyMachine<String, StrategyContext, Number> strategyMachine =  StrategyMachineFactory.get("test");
        System.out.println(strategyMachine.apply("加法", new StrategyContext(1, 2, 1)));
        System.out.println(strategyMachine.apply("减法", new StrategyContext(1, 2, 1)));
        System.out.println(strategyMachine.apply("乘法", new StrategyContext(1, 2, 1)));
        System.out.println(strategyMachine.apply("除法", new StrategyContext(1, 2, 1)));
        System.out.println(strategyMachine.apply("除法", new StrategyContext(1, 2, 2)));

源码地址: https://github.com/zhangpan-soft/dv-commons

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一些 Java 设计模式的重点内容,供您参考: 1. 设计模式的定义和分类 - 设计模式是对软件设计中普遍存在的问题的解决方案的描述。 - 设计模式可以分为三类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)和行为型模式(Behavioral Patterns)。 2. 创建型模式 - 创建型模式用于处理对象的创建过程,封装了对象的实例化过程,并提供了更加灵活的对象创建方式。 - 创建型模式包括单例模式、工厂方法模式、抽象工厂模式、建造者模式和原型模式。 3. 结构型模式 - 结构型模式用于处理类或对象的组合,以便更好地实现系统的功能。 - 结构型模式包括适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式和享元模式。 4. 行为型模式 - 行为型模式用于处理类或对象之间的通信,以及对算法和流程的控制。 - 行为型模式包括策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式和中介者模式。 5. 单例模式 - 单例模式是一种创建型模式,它保证一个类只有一个实例,并提供了一个全局访问点。 - 单例模式的核心在于将类的构造方法私有化,并提供一个静态方法来获取类的唯一实例。 6. 工厂方法模式 - 工厂方法模式是一种创建型模式,它将对象的创建委托给子类。 - 工厂方法模式的核心在于定义一个抽象工厂类,它包含一个抽象的工厂方法,用于创建产品;然后定义一个具体的工厂类,实现抽象工厂方法,并且创建具体的产品。 7. 抽象工厂模式 - 抽象工厂模式是一种创建型模式,它提供一个接口,用于创建一系列相关或相互依赖的对象。 - 抽象工厂模式的核心在于定义一个抽象工厂接口,它包含一些抽象的工厂方法,用于创建一系列相关或相互依赖的对象;然后定义一个具体的工厂类,实现抽象工厂接口,并且创建具体的产品。 8. 建造者模式 - 建造者模式是一种创建型模式,它将一个复杂对象的构建过程分解为多个简单对象的构建过程。 - 建造者模式的核心在于定义一个抽象的建造者类,它包含一些抽象的建造方法,用于构建不同的部件;然后定义一个具体的建造者类,实现抽象建造者类,并且构建具体的部件;最后定义一个指挥者类,它用于控制建造过程,以及返回最终构建的对象。 9. 原型模式 - 原型模式是一种创建型模式,它通过复制已有的对象来创建新的对象。 - 原型模式的核心在于定义一个抽象的原型类,它包含一个克隆方法,用于复制自身;然后定义一个具体的原型类,实现抽象原型类,并且实现克隆方法。 10. 适配器模式 - 适配器模式是一种结构型模式,它将一个类的接口转换成客户希望的另外一个接口。 - 适配器模式的核心在于定义一个适配器类,它包含一个客户所期望的接口,以及一个适配者对象,用于实现这个接口。 11. 装饰器模式 - 装饰器模式是一种结构型模式,它动态地给一个对象添加一些额外的职责,而不需要修改它的代码。 - 装饰器模式的核心在于定义一个装饰器类,它包含一个被装饰者对象,并且实现与被装饰者相同的接口;然后定义一个具体的装饰器类,用于添加额外的职责。 12. 代理模式 - 代理模式是一种结构型模式,它给一个对象提供一个代理对象,并由代理对象控制对原对象的访问。 - 代理模式的核心在于定义一个代理类,它包含一个与被代理类相同的接口,并且持有一个被代理对象的引用;然后在代理类中控制对被代理对象的访问。 13. 外观模式 - 外观模式是一种结构型模式,它为一组复杂的子系统提供一个简单的接口,以方便客户端的访问。 - 外观模式的核心在于定义一个外观类,它包含一组与子系统相关的操作方法,用于简化客户端的访问。 14. 桥接模式 - 桥接模式是一种结构型模式,它将抽象部分和实现部分分离,以便它们可以独立地变化。 - 桥接模式的核心在于定义一个抽象部分的接口,以及一个实现部分的接口,然后在抽象部分中持有一个实现部分的引用,用于将两者关联起来。 15. 组合模式 - 组合模式是一种结构型模式,它将对象组合成树形结构以表示“部分-整体”的层次结构,使得客户端可以统一地处理单个对象和组合对象。 - 组合模式的核心在于定义一个组件抽象类,它包含一些公共的操作方法,然后定义一个叶子组件类和一个容器组件类,分别实现组件抽象类。 16. 策略模式 - 策略模式是一种行为型模式,它定义了一系列算法,并将每个算法封装起来,使得它们可以相互替换。 - 策略模式的核心在于定义一个策略接口,它包含一个算法方法;然后定义一系列具体的策略类,分别实现策略接口中的算法方法。 17. 模板方法模式 - 模板方法模式是一种行为型模式,它定义了一个算法的框架,并将一些步骤延迟到子类中实现。 - 模板方法模式的核心在于定义一个抽象类,它包含一个算法框架方法,以及一些抽象的步骤方法;然后定义具体的子类,实现抽象的步骤方法。 18. 观察者模式 - 观察者模式是一种行为型模式,它定义了一种一对多的依赖关系,使得多个观察者对象同时监听某一个主题对象。 - 观察者模式的核心在于定义一个主题接口,它包含一些注册和移除观察者对象的方法,以及一个通知观察者的方法;然后定义一个具体的主题类,实现主题接口,并且维护一个观察者列表。 19. 迭代器模式 - 迭代器模式是一种行为型模式,它提供一种方法来访问聚合对象中的各个元素,而又不暴露该对象的内部表示。 - 迭代器模式的核心在于定义一个迭代器接口,它包含一些访问聚合对象中元素的方法;然后定义一个具体的迭代器类,实现迭代器接口,并且维护一个指向当前元素的指针。 20. 责任链模式 - 责任链模式是一种行为型模式,它将请求的发送者和接收者解耦,并且沿着一条链传递该请求,直到有一个接收者处理它。 - 责任链模式的核心在于定义一个处理请求的抽象类,它包含两个方法:处理请求和设置下一个处理者;然后定义具体的处理者类,实现抽象类中的处理请求方法。 21. 命令模式 - 命令模式是一种行为型模式,它将一个请求封装成一个对象,使得可以将请求的参数化、队列化、记录化,并且支持可撤销操作。 - 命令模式的核心在于定义一个命令接口,它包含一个执行方法和一个撤销方法;然后定义一个具体的命令类,实现命令接口,并且持有一个接收者对象的引用。 22. 备忘录模式 - 备忘录模式是一种行为型模式,它将一个对象的状态保存在一个备忘录对象中,以便可以恢复到之前的状态。 - 备忘录模式的核心在于定义一个备忘录类,它用于保存对象的状态;然后定义一个发起人类,它包含一个备忘录对象的引用,以及一些用于修改状态的方法。 23. 状态模式 - 状态模式是一种行为型模式,它允许对象在内部状态发生改变时改变它的行为。 - 状态模式的核心在于定义一个状态接口,它包含一些方法,用于在状态发生改变时改变对象的行为;然后定义具体的状态类,实现状态接口,并且在状态发生改变时改变对象的状态。 24. 访问者模式 - 访问者模式是一种行为型模式,它将算法与对象结构分离,使得可以在不改变对象结构的情况下定义新的操作。 - 访问者模式的核心在于定义一个访问者接口,它包含一些访问不同类型元素的方法;然后定义一个元素接口,它包含一个接受访问者的方法;最后定义具体的访问者类和元素类,分别实现访问者接口和元素接口。 25. 中介者模式 - 中介者模式是一种行为型模式,它定义一个中介对象,用于封装一组对象之间的交互。 - 中介者模式的核心在于定义一个中介者接口,它包含一些用于交互的方法;然后定义一个具体的中介者类,实现中介者接口,并且维护一组相关的对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值