В чем разница между шаблонным методом и шаблонами стратегии?


161

Может кто-нибудь объяснить мне, в чем разница между шаблоном метода шаблона и шаблона стратегии?

Насколько я могу судить, они на 99% одинаковые - единственное отличие состоит в том, что шаблон шаблонного метода имеет абстрактный класс в качестве базового класса, тогда как класс стратегии использует интерфейс, который реализуется каждым конкретным классом стратегии.

Однако, что касается клиента , он потребляется точно так же - это правильно?


2
Этот пост в SO имеет лучший ответ на тот же вопрос: stackoverflow.com/questions/464524/…
Gob00st

12
Вопрос, с которым связан gob00st, - это разница между стратегией и мостом. Это не ответ на этот вопрос вообще.
Bluekeys

Ответы:


135

Основное различие между ними заключается в выборе конкретного алгоритма.

С шаблоном метода Template это происходит во время компиляции путем создания подкласса шаблона. Каждый подкласс предоставляет свой конкретный алгоритм, реализуя абстрактные методы шаблона. Когда клиент вызывает методы внешнего интерфейса шаблона, шаблон вызывает свои абстрактные методы (свой внутренний интерфейс), как требуется для вызова алгоритма.

class ConcreteAlgorithm : AbstractTemplate
{
    void DoAlgorithm(int datum) {...}
}

class AbstractTemplate
{
    void run(int datum) { DoAlgorithm(datum); }

    virtual void DoAlgorithm() = 0; // abstract
}

Напротив, шаблон «Стратегия» позволяет выбирать алгоритм во время выполнения путем локализации . Конкретные алгоритмы реализуются отдельными классами или функциями, которые передаются стратегии в качестве параметра ее конструктору или методу-установщику. Какой алгоритм выбран для этого параметра, может динамически меняться в зависимости от состояния программы или входных данных.

class ConcreteAlgorithm : IAlgorithm
{
    void DoAlgorithm(int datum) {...}
}

class Strategy
{
    Strategy(IAlgorithm algo) {...}

    void run(int datum) { this->algo.DoAlgorithm(datum); }
}

В итоге:

  • Шаблонный шаблон: выбор алгоритма во время компиляции по подклассам
  • Шаблон стратегии: время выполнения алгоритма выбора по локализации

47
Оба шаблона поддерживают выбор используемого алгоритма во время выполнения (для Шаблонного метода вы бы сделали что-то подобное if (config.useAlgoA) impl = new AlgoA() else impl = new AlgoB()), поэтому этот ответ неверен.
Борек Бернард

13
Конечно, вы можете сделать это, но тогда вы не используете шаблон шаблона. Фактически, именно так будет выглядеть код, создающий экземпляр Strategy!
The House

21
-1, я думаю, что этот ответ (хотя и не совсем неправильный), упускает точку, где есть реальные различия. Ответ @ tvanfosson намного лучше.
Док Браун

1
@Karoly Nyisztor Они оба могут «заменить поведение» и «предоставить точки расширения». Является ли что-то поведением или расширением, это действительно зависит от того, где вы применяете данный шаблон. Вы также можете называть каждый подкласс шаблона метода шаблона «стратегией» или называть каждый класс стратегии в шаблоне стратегии «расширением», это просто формулировка. Дело в том, что они делают то же самое, ЗА ИСКЛЮЧЕНИЕМ разницы, о которой упоминает этот ответ. Так что это правильный ответ.
Энди

1
Конкретный алгоритм выбирается одинаково для обоих шаблонов. Выбор сделан путем обращения new ConcreteAlgorithm1()против new ConcreteAlgorithm2(). Очевидно, что выбор происходит во время выполнения (выбор алгоритма во время компиляции будет означать его жесткое программирование). Основное различие между ними заключается в том, как реализован конкретный алгоритм. Это реализовано как подкласс или как отдельный интерфейс? Первый шаблон. Последнее является стратегией. Различие можно суммировать как состав против наследования, что является общей темой книги GoF.
jaco0646

138

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

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

Две модели могут быть легко использованы вместе. У вас может быть шаблон стратегии, в котором несколько реализаций принадлежат семейству стратегий, реализованных с использованием шаблонного шаблона.


Это звучит правильно для меня, однако, почему WikiPedia упоминает, что «шаблон стратегии предназначен для выбора поведения алгоритма во время выполнения»? Это также может быть использовано для выбора поведения алгоритма во время компиляции, как метод шаблона? Я что-то упускаю?
BornToCode

2
@BornToCode Я бы предположил, что они говорят о выборе конкретной стратегии во время выполнения. Например, существует несколько способов численного нахождения корней уравнения. В зависимости от предметной области или данных вы можете выбрать Ньютона-Рафсона, Эйлера или другую стратегию решения уравнения. Каждый из них является стратегией. Более крупный алгоритм, частью которого является решение уравнения, выбирает стратегию для использования на основе некоторого качества задачи.
tvanfosson

Да, но это не значит, что шаблон стратегии должен использоваться ТОЛЬКО для этих случаев? Я имею в виду, если мне нужно только выбрать поведение алгоритма во время компиляции, должен ли я по-прежнему использовать шаблон стратегии, или он не должен был использоваться таким образом?
BornToCode

1
@BornToCode Я бы сказал, что стратегия наиболее полезна, когда выбор является динамичным. Шаблон в основном представляет собой способ построения различных, связанных поведений для известных. Вы бы использовали некоторую стратегию (хотя не обязательно шаблон стратегии) ​​для выбора шаблонного поведения для использования. Например, наследование продукта - вы создадите базовый продукт, добавите функции для различных продуктов. Выбор типа продукта (класса) для создания экземпляра может зависеть от того, из каких таблиц / представлений он загружен. Стратегический паттерн на самом деле не входит в игру.
tvanfosson

2
@BornToCode это не то или иное, это да-и-то. Применяйте шаблон там, где это уместно, комбинируйте шаблоны там, где это полезно.
tvanfosson


24

Вы, вероятно, имеете в виду шаблонный шаблон. Вы правы, они удовлетворяют очень похожие потребности. Я бы сказал, что лучше использовать метод шаблона в тех случаях, когда у вас есть «шаблонный» алгоритм, имеющий определенные шаги, где подклассы переопределяют эти шаги, чтобы изменить некоторые детали. В случае стратегии вам нужно создать интерфейс, и вместо наследования вы используете делегирование. Я бы сказал, что это немного более мощный шаблон и, возможно, лучше в соответствии с принципами инверсии зависимостей DIP. Он более мощный, потому что вы четко определяете новую абстракцию стратегии - способ сделать что-то, что не относится к шаблонному методу. Итак, если эта абстракция имеет смысл - используйте ее. Однако использование шаблонного метода может дать вам более простые конструкции в простых случаях, что также важно. Подумайте, какие слова подходят лучше: у вас есть шаблон алгоритма? Или ключевым моментом здесь является то, что у вас есть абстракция стратегии - новый способ сделать что-то

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

Application.main()
{
Init();
Run();
Done();
}

Здесь вы наследуете от приложения и подставляете, что именно будет сделано при инициализации, запуске и выполнении.

Пример стратегии:

array.sort (IComparer<T> comparer)

Здесь при написании компаратора вы не наследуете от массива. Array делегирует алгоритм сравнения для сравнения.


3
Я думаю, что это отличный ответ
Калан

23

Разница между стратегией и методом шаблона Шаблон стратегии против метода шаблона


сходства

Шаблоны стратегий и шаблонных методов имеют много общего между ними. Шаблоны методов Стратегии и Шаблонов могут использоваться для удовлетворения принципа Открыто-Закрыто и упрощения расширения программного модуля без изменения его кода. Оба шаблона представляют отделение общей функциональности от детальной реализации этой функциональности. Тем не менее, они немного отличаются с точки зрения гранулярности, которую они предлагают.


Различия

Вот некоторые из различий, которые я наблюдал при изучении этих двух моделей:

  1. В Стратегии связь между клиентом и стратегией более свободна, тогда как в Шаблонном методе два модуля более тесно связаны.
  2. В Стратегии в основном используется интерфейс, хотя абстрактный класс также может использоваться в зависимости от ситуации, а конкретный класс не используется, тогда как в методе Template в основном используется абстрактный класс или конкретный класс, интерфейс не используется.
  3. В паттерне Стратегия, как правило, все поведение класса представлено в виде интерфейса, с другой стороны, метод Template используется для уменьшения дублирования кода, а шаблонный код определяется в базовой структуре или абстрактном классе. В Template Method может быть даже конкретный класс с реализацией по умолчанию.
  4. Проще говоря, вы можете изменить всю стратегию (алгоритм) в шаблоне «Стратегия», однако в методе «Шаблон» изменяются только некоторые вещи (части алгоритма), а остальные остаются неизменными. В шаблонном методе инвариантные шаги реализованы в абстрактном базовом классе, в то время как вариантные шаги либо имеют реализацию по умолчанию, либо не имеют реализации вообще. В методе Template разработчик компонента назначает необходимые шаги алгоритма и упорядочивает шаги, но позволяет клиенту компонента расширять или заменять некоторое количество этих шагов.

Изображение взято из укушенного блога.



11

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

Разница между ними заключается в том, что, хотя шаблон стратегии позволяет различным реализациям использовать совершенно разные способы достижения желаемого результата, шаблон шаблонного метода задает всеобъемлющий алгоритм («шаблонный» метод), который используется для достижения результата - - единственный выбор, оставленный конкретным реализациям (подклассам), - это определенные детали указанного метода шаблона. Это достигается путем вызова метода (ов) метода шаблона одним или несколькими абстрактными методами, которые переопределяются (то есть реализуются) подклассами, в отличие от метода шаблона, который сам не является абстрактным и не переопределяется подклассами. ,

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


9

Метод шаблона:

  1. Он основан на наследовании
  2. Определяет скелет алгоритма, который не может быть изменен подклассами. Только определенные операции могут быть переопределены в подклассах
  3. Родительский класс полностью контролирует алгоритм и отличает только определенные шаги от конкретных классов
  4. Привязка выполняется во время компиляции

Структура Template_method :

введите описание изображения здесь

Стратегия:

  1. Он основан на делегировании / составе
  2. Это изменяет внутренности объекта , изменяя поведение метода
  3. Используется для переключения между семейством алгоритмов
  4. Он изменяет поведение объекта во время выполнения, полностью заменяя один алгоритм другим алгоритмом во время выполнения.
  5. Связывание выполняется во время выполнения

Структура стратегии :

введите описание изображения здесь

Взгляните на метод шаблонов и статьи по стратегии для лучшего понимания.

Похожие сообщения:

Шаблон дизайна шаблона в JDK, не удалось найти метод, определяющий набор методов, которые должны быть выполнены в порядке

Пример шаблона стратегии в реальном мире


3

Нет, они не обязательно потребляются таким же образом. Шаблон «метод шаблона» - это способ предоставления «руководства» будущим разработчикам. Вы говорите им: «Все объекты Person должны иметь номер социального страхования» (это тривиальный пример, но он дает правильное представление).

Шаблон стратегии позволяет включать и выключать несколько возможных реализаций. Это (обычно) не реализуется через наследование, но вместо этого позволяет вызывающей стороне передать желаемую реализацию. Примером может служить предоставление ShippingCalculator одним из нескольких различных способов расчета налогов (возможно, реализация NoSalesTax и реализация PercentageBasedSalesTax).

Поэтому иногда клиент фактически сообщает объекту, какую стратегию использовать. Как в

myShippingCalculator.CalculateTaxes(myCaliforniaSalesTaxImpl);

Но клиент никогда бы не сделал это для объекта, основанного на шаблонном методе. Фактически, клиент может даже не знать, что объект основан на шаблонном методе. Эти абстрактные методы в шаблоне Template Method могут быть даже защищены, и в этом случае клиент даже не узнает, что они существуют.


3

Я бы предложил вам прочитать эту статью. Это объясняет различия на реальном примере.

Цитата из статьи

« Как можно видеть, классы реализации также зависят от класса метода шаблона. Эта зависимость вызывает изменение метода шаблона, если кто-то хочет изменить некоторые этапы алгоритма. С другой стороны, стратегия полностью инкапсулирует алгоритм. Она дает реализацию классы, чтобы полностью определить алгоритм. Поэтому, если какое-либо изменение прибывает, нужно изменить код для ранее написанных классов. Это было основной причиной, по которой я выбрал стратегию для разработки классов.

Одна особенность метода шаблона состоит в том, что метод шаблона управляет алгоритмом. Что может быть хорошо в другой ситуации, но в моей проблеме это ограничивало меня в разработке классов. С другой стороны, стратегия не контролирует этапы алгоритма, что позволяет мне добавлять совершенно разные методы преобразования. Следовательно, в моем случае стратегия помогает мне для реализации.

Одним из недостатков стратегии является то, что слишком много избыточности кода и меньше совместного использования кода. Как видно из представленного примера этой статьи, мне приходится снова и снова повторять один и тот же код в четырех классах. Поэтому трудно поддерживать, потому что, если реализация нашей системы, такой как шаг 4, которая является общей для всех, будет изменена, то мне придется обновить ее во всех 5 классах. С другой стороны, в методе шаблона я могу изменить только суперкласс, и изменения будут отражены в подклассах. Поэтому шаблонный метод дает очень низкую избыточность и большой объем совместного использования кода между классами.

Стратегия также позволяет изменять алгоритм во время выполнения. В методе шаблона нужно будет повторно инициализировать объект. Эта особенность стратегии обеспечивает большую гибкость. С точки зрения дизайна нужно отдавать предпочтение композиции, а не наследованию. Поэтому использование шаблонов стратегий также стало основным выбором для развития ».


2

Шаблон Template похож на шаблон Strategy. Эти две модели различаются по объему и методологии.

Стратегия используется для того, чтобы вызывающие абоненты могли изменять весь алгоритм, например, как рассчитывать различные типы налогов, в то время как шаблонный метод используется для изменения шагов в алгоритме. Из-за этого Стратегия является более грубой. Шаблон позволяет более детально контролировать последовательность операций, но при этом позволяет варьировать реализации этих деталей.

Другое основное отличие заключается в том, что в стратегии используется делегирование, а в шаблонном методе используется наследование. В Стратегии алгоритм делегирован другому классу xxxStrategy, на который будет ссылаться субъект, но с помощью Template вы создадите подкласс базового и переопределите методы для внесения изменений.

от http://cyruscrypt.blogspot.com/2005/07/template-vs-strategy-patterns.html


2

В подклассах шаблонов стратегий выполняется шоу, и они управляют алгоритмом. Здесь код дублируется во всех подклассах. Знание алгоритма и его реализации распространяется на многие классы.

В шаблоне шаблона базовый класс имеет алгоритм. Это максимизирует повторное использование среди подклассов. Поскольку алгоритм лежит в одном месте, базовый класс защищает его.


2

Шаблон дизайна стратегии

  • Поддерживает состав.
  • Предоставляет вам гибкость, чтобы изменить поведение объекта во время выполнения.
  • Меньшая связь между кодом клиента и кодом решения / алгоритма.

Шаблон Метод Дизайн Шаблон

  • Благоприятствует наследству по составу
  • Определите алгоритм в вашем базовом классе. Отдельные части алгоритма могут быть настроены в дочерних классах.

1

Шаблон шаблона:

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

public abstract class RobotTemplate {
    /* This method can be overridden by a subclass if required */
    public void start() {
        System.out.println("Starting....");
    }

    /* This method can be overridden by a subclass if required */
    public void getParts() {
        System.out.println("Getting parts....");
    }

    /* This method can be overridden by a subclass if required */
    public void assemble() {
        System.out.println("Assembling....");
    }

    /* This method can be overridden by a subclass if required */
    public void test() {
        System.out.println("Testing....");
    }

    /* This method can be overridden by a subclass if required */
    public void stop() {
        System.out.println("Stopping....");
    }

    /*
     * Template algorithm method made up of multiple steps, whose structure and
     * order of steps will not be changed by subclasses.
     */
    public final void go() {
        start();
        getParts();
        assemble();
        test();
        stop();
    }
}


/* Concrete subclass overrides template step methods as required for its use */
public class CookieRobot extends RobotTemplate {
    private String name;

    public CookieRobot(String n) {
        name = n;
    }

    @Override
    public void getParts() {
        System.out.println("Getting a flour and sugar....");
    }

    @Override
    public void assemble() {
        System.out.println("Baking a cookie....");
    }

    @Override
    public void test() {
        System.out.println("Crunching a cookie....");
    }

    public String getName() {
        return name;
    }
}

Обратите внимание, что в приведенном выше коде шаги алгоритма go () всегда будут одинаковыми, но подклассы могут определять другой рецепт для выполнения определенного шага.

Шаблон стратегии:

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

/**
 * This Strategy interface is implemented by all concrete objects representing an
 * algorithm(strategy), which lets us define a family of algorithms.
 */
public interface Logging {
    void write(String message);
}

/**
 * Concrete strategy class representing a particular algorithm.
 */
public class ConsoleLogging implements Logging {

    @Override
    public void write(String message) {
        System.out.println(message); 
    }

}

/**
 * Concrete strategy class representing a particular algorithm.
 */
public class FileLogging implements Logging {

    private final File toWrite;

    public FileLogging(final File toWrite) {
        this.toWrite = toWrite;
    }

    @Override
    public void write(String message) {
        try {
            final FileWriter fos = new FileWriter(toWrite);
            fos.write(message);
            fos.close();
        } catch (IOException e) {
            System.out.println(e);
        }
    }

}

Полный исходный код можно найти в моем репозитории github .


0

Стратегия представлена ​​как интерфейс и метод шаблона как абстрактный класс. Обычно это часто используется в рамках. Например, класс MessageSource платформы Spring - это интерфейс стратегии для разрешения сообщений. Клиент использует конкретную реализацию (стратегию) этого интерфейса.

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

http://docs.spring.io/spring/docs/4.1.7.RELEASE/javadoc-api/org/springframework/context/support/AbstractMessageSource.html


0

В методе шаблона этого шаблона проектирования один или несколько шагов алгоритма могут быть переопределены подклассами, чтобы обеспечить различное поведение при одновременном соблюдении всеохватывающего алгоритма (Wiki).

Имя шаблона Шаблонный метод означает, что это такое. Скажем, у нас есть метод CalculateSomething (), и мы хотим шаблонировать этот метод. Этот метод будет объявлен в базовом классе не виртуальным методом. Скажем, метод выглядит следующим образом.

CalculateSomething(){
    int i = 0;
    i = Step1(i);
    i++;
    if (i> 10) i = 5;
    i = Step2(i);
    return i;

} Реализация методов Step1 и Step2 может быть задана производными классами.

В паттерне стратегии нет реализации, предоставляемой базой (это причина, почему база действительно является интерфейсом на диаграмме классов)

Классический пример - сортировка. На основе количества объектов, подлежащих сортировке, создается соответствующий класс алгоритмов (слияние, всплывающие, быстрые и т. Д.), И весь алгоритм инкапсулируется в каждом классе.

Теперь мы можем реализовать сортировку как шаблонный метод? Конечно, вы можете, но вы не найдете много / каких-либо общих черт, которые можно абстрагировать и поместить в базовую реализацию. Так что это побеждает цель шаблона шаблона.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.