Отличие и применение шаблона стратегии и шаблона фабричного метода в проектах

Java

Когда мы пишем код, если много логических суждений, а если ситуация сложнее, то часто ли мы пишем такой код:在这里插入图片描述Точно так же, как груды суждений «если-иначе» на картинке выше, люди ослеплены. По сути, с элегантной точки зрения кода, это груда острой курицы, и ее вообще нельзя подавать на стол. Итак, как вам нужно оптимизировать так много if-else, как указано выше?

режим стратегии

Классический Art of War «Дзен шаблонов дизайна» имеет простое определение режима стратегии:

Определите набор алгоритмов, инкапсулируйте каждый алгоритм и сделайте их взаимозаменяемыми. . . . . Контекст называется ролью контекста, и он играет роль в инкапсуляции, защищая высокоуровневые модули от прямого доступа к политикам и алгоритмам и инкапсулируя возможные изменения. . . . .

Это описание немного абстрактно, на самом деле мы часто используем паттерн стратегии в реальной разработке. Просто мы не думаем и не уделяем слишком много внимания,Например: Вы все еще помните ThreadPoolExecutor (пул потоков), jdk предоставляет несколько пулов потоков, но не рекомендуется использовать тот, который предоставляется jdk, когда мы его используем. Как правило, нам нужно создать пул потоков самостоятельно в соответствии с конструктором (знания и вопросы, связанные с пулом потоков, будут обсуждаться в отдельной статье в следующий раз). Когда мы сами конструировали пул потоков, там был один из семи малоизвестных параметров RejectedExecutionHandler, что означает стратегию отклонения (существует четыре реализации: кидать исключение напрямую, возвращаться в поток вызывающего для обработки, отбрасывать текущий задача, выбросить самую старую задачу), суть ее — воплощение режима стратегии.

    /**
     * Handler called when saturated or shutdown in execute.
     */
    private volatile RejectedExecutionHandler handler;

	public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        //具体代码。。。
        this.handler = handler;
    }

    /**
     * Invokes the rejected execution handler for the given command.
     * Package-protected for use by ScheduledThreadPoolExecutor.
     */
    final void reject(Runnable command) {
        handler.rejectedExecution(command, this);
    }

Приходите и посмотрите этот образец стратегии со мной

Паттерн стратегии — это способ определения系列算法的方法, концептуально все эти алгоритмы достигают相同的工作, просто реализовано иначе, он может использовать相同的方式Вызов всех алгоритмов уменьшает связь между различными классами алгоритмов и использование классов алгоритмов. Теоретически, посмотрите на часть, которую я выделил выше. Имеет следующие характеристики: Шаблон стратегии: все алгоритмы режима стратегии должны выполнять одну и ту же работу, но условия срабатывания могут быть разными, поэтому мы можем абстрагироваться от шаблона стратегии. Стратегия: реализуйте различные стратегии в соответствии с конкретными сценариями, чтобы получить конкретные результаты в соответствии с реальными сценариями; Контекст: Контекст определяет, какую стратегию использовать в зависимости от сценария. Приведите пример из жизни, чтобы всем было понятно: Все мы пользовались стиральными машинами, и при стирке вещей в стиральной машине мы можем выбирать много типов (быстрая стирка, стандартная, полоскание, большая и т. с одной целью хорошо постирать вещи, способ стирки знаний вызывает различные условия, поэтому мы можем поставить洗东西После того, как это действие абстрагировано, оно становится конкретным洗的种类Это абстракция стирки вещей具体实现.

Пример кода шаблона стратегии

//洗的动作 -> 策略模板
class DoingWash {
    constructor() {}
}
// 标准洗
class Biaozhun extends DoingWash {
    constructor() {}
    doWash() {
        return "我是标准洗";
    }
}
// 快速洗
class KuaiSu extends DoingWash {
    constructor() {}
    doWash() {
        return "我是快速洗";
    }
}
// 大件洗
class DaJian extends DoingWash {
    constructor() {}
    doWash() {
        return "我是大件洗";
    }
}
// 上下文传入策略并使用
class WashContext {
    constructor(strategy) {
        this.strategy = strategy;
    }
    doingGo() {
        return this.strategy.doWash();
    }
}
// 使用
WashContext w1 = new WashContext(new Biaozhun());
w1.doWash();

Как это просто. . . Подытожим паттерн стратегии: Из приведенных примеров можно сделать вывод, что сценарии использования паттерна стратегии имеют несколько характеристик:

  • Столкнувшись с проблемой / спросом, есть несколько решений, и необходимо оценить разные сценарии.
  • меньшее количество сцен

优点就是:

  • Стратегии независимы друг от друга, а масштабируемость и ремонтопригодность относительно хороши.
  • хороший модульный тест
  • Уменьшенный переключатель / если еще решение

缺点就是:

  • Не подходит для решения слишком большого количества сценариев

Шаблон фабричного метода

После разговора о паттерне стратегии мы, кстати, поговорим о фабричном паттерне, потому что они очень похожи. Мы можем увидеть разницу между ними, сравнив их, и в этом сценарии следует использовать определенный режим. Фабричный паттерн — это паттерн, сформированный после оптимизации простого фабричного паттерна. Шаблон Factory очень похож по определению на шаблон Strategy.

Приходите посмотреть на этот шаблон фабричного метода вместе со мной

举个例子: Сейчас я занимаюсь транспортным бизнесом, перевожу товары из одного города Китая в другой, поэтому я могу выбирать различные способы транспортировки: на машине, поездом или самолетом. Это реализация перевозки вещей, то есть какой транспорт используется. Что ж, мы можем абстрагироваться от концепции, называемой транспортировкой вещей, а конкретная вещь, связанная с транспортировкой вещей, может быть реализована в трех вышеупомянутых формах. Мне все равно, какой инструмент используется для доставки, это зависит от подкласса (火车,飞机,汽车) достигать.

Давайте посмотрим на пример кода

class TransPortSThing {
    constructor() {}
    transGo() {
        // 我只定义要运输具体怎么运输子类都要实现transGo方法
    }
}
// 汽车
class Qiche extends TransPortSThing {
    constructor() {}
    transGo() {
        return "我是汽车";
    }
}
// 火车
class Huoche extends TransPortSThing {
    constructor() {}
    transGo() {
        return "我是火车";
    }
}
// 飞机
class FeiJi extends TransPortSThing {
    constructor() {}
    transGo() {
        return "我是飞机";
    }
}
// 使用 --用火车运输
TransPortSThing yunDongXi = new Huoche();
yunDongXi.transGo();

// 使用 --用飞机运输
TransPortSThing yunDongXi = new FeiJi();
yunDongXi.transGo();

Приведенный выше код может быть вызван после написания класса инструмента и динамического получения объекта подкласса класса TransPortSThing в соответствии с параметрами. Из вышеизложенного нетрудно увидеть, что эти два шаблона проектирования очень похожи. Подытожим этот шаблон фабричного метода:

  1. Избегайте привязки создателей к конкретной логике продукта.
  2. Удовлетворяя единой ответственности, каждая реализация бизнес-логики выполняется в своем собственном классе.
  3. Удовлетворяя принципу открытия-закрытия, новые реализации могут быть введены в программу без изменения вызывающей стороны.

сравнение двух

Мы видим, что два приведенных выше шаблона проектирования очень похожи, поэтому давайте сравним их подробно.再总结一下. Объясните двумя картинками:在这里插入图片描述 在这里插入图片描述Таким образом, каждый может интуитивно почувствовать разницу между ними. Разница между паттерном стратегии и фабричным паттерном:工厂模式1. Цель состоит в том, чтобы создать отдельные и связанные объекты 2. Сосредоточьтесь на «создании объектов» 3. Способ реализации может быть через родительский класс или интерфейс 4. Как правило, созданный объект должен быть отображением чего-то в реальном мире, со своими свойствами и методами!策略模式1. Цель состоит в том, чтобы легко заменить различные классы алгоритмов 2. Сосредоточьтесь на реализации алгоритма (поведения) 3. Реализация в основном через интерфейс 4. Создайте объект, который абстрагирует поведение, а не сам объект, и, возможно, не имеет собственных свойств. `

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