极简策略模式2.0(妙用枚举)

4,365 阅读5分钟

吐槽

要先吐槽!先得吃瓜!请移步稍微阅读一哈上一篇关于极简策略模式的文章,深入笔者的心路历程,一起思考,一起学习,一起嗨皮!戳-->极简策略模式1.0...咳咳,我们严肃点,毕竟是程序员!要木讷刻板,笔者写完文章后,也颇为自得,发给了同学、朋友、某神奇的群,然后友好的程序员朋友们,就欢快的吐槽了起来,气氛一下子就起来了,他们主要指出(攻击)了以下的问题:

  1. 钩子与处理逻辑使用Pair结合太过麻烦(笔者觉得他们是在挑刺)
  2. 使用List来存放策略是可以的,但是不觉得泛型写得有点多么(又不是你手写,你怕啥?)
  3. 策略初始化以及使用非常不明显,层次不清晰,冗余复杂(笔者也觉得,我内心只承认这一点)

求索

听完大家友好的反馈以后,我很泄气,决定放弃,全文完...

别急,笔者在某种机缘巧合之下看到了一些关于枚举的文章,发现枚举很妙,有了一些大胆的想法

  1. 枚举在加载时已经初始化,能有效的将使用和初始化分离
  2. 枚举结合的策略方法可以隐藏策略实现的细节,封装相关逻辑
  3. 枚举的增加和修改是非常清晰的,枚举的名称可以有效的指出当前策略的逻辑

码一码(故事纯属虚构,如有雷同,你肯定抄我的)

年关将近,大家关心的当然是怎么给爽子洗白,哦不是,是川普离职了下家去哪里,不!!!!最关心的是打工人 能不能回家过年,笔者也是个打工人,灵机一动,给村里提供了一套先进的系统,过滤打工人的回乡请求,具体的逻辑实现如下面所示

1.村里直接拦路了,打工人直接原路返回

每一次拦路处理的逻辑抽象应该是这样的

public interface ConsumerStrategy<P, C> {

    /**
     * 暴露当前策略的钩子
     *
     * @return 判断钩子
     */
    Predicate<P> predicate();

    /**
     * 暴露当前策略的消费逻辑
     *
     * @return 消费逻辑
     */
    Consumer<C> consumer();

    /**
     * 真实的消费数据
     *
     * @param p 钩子来源
     * @param c 消费来源
     */
    default void handle(P p, C c) {
        if (this.predicate().test(p)) {
            this.consumer().accept(c);
        }
    }
}

系统维护了一套拦路询问逻辑,具体逻辑如下

/**
 * 简化处理
 * String 代表来自区域风险系数
 * Integer 打工人
 */
enum ReturnHomeStrategy implements ConsumerStrategy<String, Integer> {
    /**
     * 高风险
     */
    HIGH_RISK(from -> "HIGH_RISK".equals(from), i -> {
        throw new RuntimeException("滚!");
    }),
    /**
     * 中风险
     */
    MIDDLE_RISK(from -> "MIDDLE_RISK".equals(from), i -> {
        throw new RuntimeException("滚!");
    }),
    /**
     * 低风险
     */
    LOW_RISK(from -> "LOW_RISK".equals(from), i -> {
        //todo 如果可以,也请滚
        //todo 核算检测
        //todo 居家隔离
    });

    private final Predicate<String> predicate;

    private final Consumer<Integer> consumer;

    ReturnHomeStrategy(Predicate<String> predicate, Consumer<Integer> consumer) {
        this.predicate = predicate;
        this.consumer = consumer;
    }

    @Override
    public Predicate<String> predicate() {
        return this.predicate;
    }

    @Override
    public Consumer<Integer> consumer() {
        return this.consumer;
    }
}

系统运行情况如下

/**
 * 某人回家
 *
 * @param from 代表来自区域风险系数
 * @param id   打工人
 */
public void returnHome(String from, Integer id) {
    for (ReturnHomeStrategy value : ReturnHomeStrategy.values()) {
        value.handle(from, id);
    }
}

系统运行了一段时间以后,广受好评,成功的保护了笔者村庄的安全,只是村长觉得,不够人性化,没有人文主义关怀,问笔者有没有好的方法,笔者肚子一晃,坏水一抖,说要不给他们开一个证明吧,有理有据的那种,体现村里的关爱,村长深深的看了笔者一眼,微微点了下头

2.村里直接拦路了,但是给开了书面证明,系统2.0上线了

改版以后,每一次拦路处理的逻辑抽象应该是这样的

public interface FunctionStrategy<P, T, R> {

    /**
     * 暴露当前策略的钩子
     *
     * @return 判断钩子
     */
    Predicate<P> predicate();

    /**
     * 暴露当前策略的生产逻辑
     *
     * @return 消费逻辑
     */
    Function<T, R> function();
}

系统维护新的拦路并签发书面证明的逻辑

/**
 * 简化处理
 * String 代表来自区域风险系数
 * Integer 打工人
 * String 村里开具证明
 */
enum ReturnHomeStrategy implements FunctionStrategy<String, Integer, String> {
    /**
     * 高风险
     */
    HIGH_RISK(from -> "HIGH_RISK".equals(from), i -> "滚!"),
    /**
     * 中风险
     */
    MIDDLE_RISK(from -> "MIDDLE_RISK".equals(from), i -> "滚!"),
    /**
     * 低风险
     */
    LOW_RISK(from -> "LOW_RISK".equals(from), i -> "村里的祸害回来了,给他做个核算检测!");

    private final Predicate<String> predicate;

    private final Function<Integer, String> function;

    public Predicate<String> getPredicate() {
        return predicate;
    }

    public Function<Integer, String> getFunction() {
        return function;
    }

    ReturnHomeStrategy(Predicate<String> predicate, Function<Integer, String> function) {
        this.predicate = predicate;
        this.function = function;
    }

    @Override
    public Predicate<String> predicate() {
        return this.predicate;
    }

    @Override
    public Function<Integer, String> function() {
        return this.function;
    }
}

系统再次运行情况如下

/**
 * 某人回家
 *
 * @param from 代表来自区域风险系数
 * @param id   打工人
 * @return 要证明
 */
public String returnHome(String from, Integer id) {
    for (ReturnHomeStrategy value : ReturnHomeStrategy.values()) {
        if (value.predicate().test(from)) {
            return value.function().apply(id);
        }
    }
    throw new RuntimeException("外星人,抓起来放进动物园卖门票!");
}

系统终于完美的上线了,世界真美好,空气真清新,就是村里笔者爱的小花也被拦在了村外,真是让人惆怅

正经总结

愚者千虑,必有一得笔者一直在思考各种设计模式的简化版的写法,比如原来也写过管道模式的简化版(别去看,思考欠佳,怕丢人),本篇文章也是多次思考修改所得,也是希望大家能够获得一些灵感,让设计模式不再是重构甚至重开项目时的选择,让策略简单化,成为我们能用,易用,随心用的代码模板,增加编码效率,拥抱健康生活,祝好,谢谢!