Минималистский режим стратегии

Шаблоны проектирования

мышление

Недавно из-за рефакторинга проекта у меня появилось время преобразовать старый код, я обнаружил, что многие интерфейсы были хорошо спроектированы в начале, но под вторжением различных требований они становились все более и более сложными.混乱, которая со временем превратилась в так называемую"куча мусора", различныйIF-ELSEЛетая по всему небу, человек, который принял управление, много жаловался, и в конце концов они могли только пахнуть恶臭, зажми нос и продолжай"куча мусора"Вбрасывать мусор. Наконец, мусорная свалка рухнула, и новый проект был вновь открыт.

Дилемма

  1. IF-ELSEКодовых блоков много, а время преобразования короткое, что не подходит для"переломы костей"
  2. Устранить с помощью режима стратегииIF-ELSEБлок кода сложен, а объем кода велик, что приводит к добавлению множества классов политик.
  3. Максимально возможное повторное использование существующей логики без добавления нового кода.

доход

правильноJava8Пользуюсь давно, очень нравится"Steam"Что касается обработки данных, я чувствую, что вообще не пишу Java-код, там нет сложного кода, а написан упрощенный код, а. . . Не по теме, на самом деле лучше всего сказатьJava8недавно добавленный пакет"Function",Так называемый"функциональный"Программирование, конечно, не говорит, является ли это функциональное программирование ослабленной версией, на самом деле под этим пакетом есть много хороших инструментов, которые могут упростить нам работу

Примечание. Следующий код дает только основную часть, пожалуйста, проверьте исходный код для других методов.

  1. Predicate BiPredicate

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);
}
@FunctionalInterface
public interface BiPredicate<T, U> {
    boolean test(T t, U u);
}

Первый инструмент"Predicate", какова его роль? Как следует из названия, он предлагает оценочную логику, которую может заменить"режим стратегии"середина"крюк"метод,"крюк"Конечно, метод заключается в том, чтобы решить, какую стратегию использовать для обработки текущей логики."крюк"может быть обеспечен фабричным методом, но выбор стратегии минималистского режима будет"крюк"внутри стратегии P.S. Вот два"Predicate"Всем удобно обрабатывать множество входных параметров

  1. Consumer Function
//Consumer
@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
}
@FunctionalInterface
public interface BiConsumer<T, U> {
    void accept(T t, U u);
}
//Function
@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
}
@FunctionalInterface
public interface BiFunction<T, U, R> {
    R apply(T t, U u);
}

Второй инструментConsumerилиFunction, два инструмента представляют две ситуации обработки стратегии, а именно: первая: чистое потребление (запасы и т. д.), вторая: производство (отфильтрованные данные и т. д.), они используются для замены части стратегии в режиме стратегии, отказаться от написание сложных интерфейсов стратегии и классов реализации стратегии упрощают масштабирование шаблонов стратегии, сокращая затраты на код и время

  1. Pair
// 笔者使用org.springframework.data.util下的Pair工具
// 因为不需要引入其他依赖
// PS: Pair的实现很多,可以自行选择食用
public final class Pair<S, T> {
    @NonNull
    private final S first;
    @NonNull
    private final T second;

    public static <S, T> Pair<S, T> of(S first, T second) {
        return new Pair(first, second);
    }

    public S getFirst() {
        return this.first;
    }

    public T getSecond() {
        return this.second;
    }
}

Это понятно,"Pair"используется для хранения политик, таких что"крюк"а также"логика политики"собраны, чтобы сформировать"Блок обработки политик", грубо говоря, это контейнер для инструментов.Есть много видов контейнеров.Вы можете найти тот, который вам нравится.Автор просто выбирает ближайший.

пытаться

Люди часто спрашивают в группе, что они на самом деле пишут свои собственныеMainВопрос можно проверить методом, и тогда у всех вопрос и ответ: попробуй сам! Поэтому программисты должны попробовать себя, так что попробуйте сначала

  1. Первый шаг — найти блок IF-ELSE.

一个简单权限过滤功能,可以写出3个IF嵌套,逻辑复杂一点呢?

//PowerQuery结构在下方
public List<String> filterPowerByQuery(List<String> powers, PowerQuery query) {
        if ("ALL".equalsIgnoreCase(query.getType())) {
            //内部用户和外部用户ALL返回全部
            return powers;
        }
        if (new Integer(0).equals(query.getUserType())) {
            //内部用户
            if (StringUtils.isNotBlank(query.getPowerName())) {
                //内部用户可以查看 类型  权限 (以PowerName为前缀)
                return powers.stream()
                             .filter(s -> StringUtils.startsWithIgnoreCase(s, query.getPowerName()))
                             .collect(Collectors.toList());
            }
            //内部用户其他情况
            return powers;
        } else {
            //非ALL的情况下,外部用户一次只能查看一种权限的数据
            return powers.stream()
                         .filter(s -> StringUtils.equals(query.getPowerName(), s))
                         .collect(Collectors.toList());
        }
    }

PowerQuery的结构,简单三个属性

@Data
public class PowerQuery {
    /**
     * ALL-全部
     * 其他值-无效
     */
    private String type;

    /**
     * 0-内部
     * 1-外部
     */
    private Integer userType;

    /**
     * 如果不是ALL角度查看
     * 外部用户一次只能查看一个权限
     */
    private String powerName;
}

  1. Пан его
public List<String> filterPowerByStrategy(List<String> allPowers, PowerQuery powerQuery) {
        //这个例子中策略模式有明显的链式的规则
        //但是使用List也可以很好地反应这种规则
        //类似Spring的DispatchServlet中的各种Resolver等也是List组织的
        List<Pair<Predicate<PowerQuery>, BiFunction<List<String>, PowerQuery, List<String>>>> chains = new ArrayList<>();
        //ALL的逻辑
        chains.add(Pair.of(query -> "ALL".equalsIgnoreCase(query.getType()), (powers, query) -> powers));
        //这里将外部用户的逻辑提到上部
        chains.add(Pair.of(query -> new Integer(1).equals(query.getUserType()), (powers, query) -> powers));
        //内部用户且PowerName有值
        chains.add(Pair.of(query -> new Integer(0).equals(query.getUserType()) && StringUtils.isNotBlank(query.getPowerName()),
                           (powers, query) -> powers.stream()
                                                    .filter(s -> StringUtils.startsWithIgnoreCase(s, query.getPowerName()))
                                                    .collect(Collectors.toList())));
        //最后增加一个收尾的策略 其他情况统一返回原全量权限
        chains.add(Pair.of(query -> true, (powers, query) -> powers));
        //使用策略List
        for (Pair<Predicate<PowerQuery>, BiFunction<List<String>, PowerQuery, List<String>>> chain : chains) {
            if (chain.getFirst().test(powerQuery)) {
                return chain.getSecond().apply(allPowers, powerQuery);
            }
        }
        //这个逻辑是不会走的
        return allPowers;
    }
  1. описание метода

Сначала отсортируйте существующую логику, отделите логику обработки стратегии и пропустите каждую стратегию черезPredicateа такжеFunctionорганизованы в кластеры методов в шаблоне стратегии и, наконец, через"цикл из"путь стратегии"крюк хит", логика стратегии"запустить обработку", у агента на самом деле много следов подражания, таких как использование стратегий"List"организация,"цикл из"выполнить логическую обработку

заключение

Автор очень喜欢策略模式Да, а также постараюсь использовать паттерн стратегии в ежедневной разработке. В процессе практики я также понял, что режим стратегии имеет определенный порог для использования, и я чувствую, что режим стратегии тяжел, и каждый раз, когда я пытаюсь его реализовать, это топ-уровень."Интерфейс политики"плюс куча стратегий"реализовать кластер методов", а на самом деле обычно больше всего нужна стратегия на самом делеIF-ELSE, но сделать это было бы очень хлопотно, и брат, который взял на себя управление, тоже был сбит с толку и закричал: «Пожалуйста, дайте мне немного понаблюдать за этим». . . Эта минималистская стратегия"просто", не добавляйте слишком много классов и интерфейсов, простое преобразованиеIF-ELSE, объем кода значительно не увеличился, а также поддерживает"Быстрая экспансия", как сказано в тексте, это действительно результат размышлений после изменения. В то же время следует указать, что это также автор"за закрытыми дверями"В результате слова семьи неизбежно упущены.Сегодняшний обмен также должен вдохновить вас, привлечь других, найти точки соприкосновения, сохраняя при этом различия, если у вас есть какие-либо идеи, пожалуйста, оставьте сообщение ниже, и каждый может обсудить