Чим відрізняється шаблонний метод від шаблону стратегії?


161

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

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

Однак, що стосується клієнта , вони споживаються точно так само - чи правильно це?


2
Це повідомлення в SO має найкращу відповідь на те ж питання: stackoverflow.com/questions/464524 / ...
Gob00st

12
Питання gob00st, пов'язане з цим, полягає в різниці між стратегією та мостом. Це зовсім не відповідь на це питання.
сині клаптики

Відповіді:


135

Основна відмінність між ними полягає у виборі конкретного алгоритму.

З шаблоном методу Шаблон це відбувається під час компіляції шляхом підкласифікації шаблону. Кожен підклас забезпечує інший конкретний алгоритм, реалізуючи абстрактні методи шаблону. Коли клієнт викликає методи зовнішнього інтерфейсу шаблону, він називає його абстрактні методи (його внутрішній інтерфейс) у міру необхідності для виклику алгоритму.

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
Обидва шаблони підтримують підбір виконуваного алгоритму (для методу Template, ви б зробили щось подібне if (config.useAlgoA) impl = new AlgoA() else impl = new AlgoB()), тому ця відповідь є невірною.
Борек Бернар

13
Звичайно, ви могли це зробити, але тоді ви не використовуєте шаблон шаблону. Насправді, саме так виглядатиме код, що створює екземпляр Strategy!
будинок

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();
}

Тут ви успадковуєте від програми та заміняєте, що саме буде зроблено на init, run та done.

Приклад стратегії:

array.sort (IComparer<T> comparer)

Тут, пишучи компаратор, ви не успадковуєте з масиву. Масив делегує алгоритм порівняння порівняльнику.


3
Я думаю, що це чудова відповідь
Каланус

23

Різниця між стратегією та методом шаблону Шаблон стратегії від методу шаблону


Подібність

Шаблони методів стратегії та шаблону мають багато подібності між собою. Як схеми методів стратегії, так і шаблонів можна використовувати для задоволення принципу відкритого закриття та полегшення розширення програмного модуля без зміни коду. Обидві моделі представляють відокремлення загальної функціональності від детальної реалізації цієї функціональності. Однак вони дещо відрізняються з точки зору деталізації, яку вони пропонують.


Відмінності

Ось деякі відмінності, які я спостерігав під час вивчення цих двох моделей:

  1. У стратегії зв'язок між клієнтом і стратегією є більш слабким, тоді як у методі шаблону два модулі більш щільно з'єднані.
  2. У стратегії використовується в основному інтерфейс, хоча абстрактний клас також може бути використаний залежно від ситуації, а конкретний клас не використовується, тоді як у методі шаблонів використовується переважно абстрактний клас або конкретний клас, інтерфейс не використовується.
  3. У шаблоні стратегії, як правило, вся поведінка класу представлена ​​в інтерфейсі, з іншого боку, метод шаблону застосовується для зменшення дублювання коду, а код котлопласту визначається в базовій рамці або абстрактному класі. У методі шаблонів навіть може бути конкретний клас із реалізацією за замовчуванням.
  4. Простими словами, ви можете змінити всю стратегію (алгоритм) у шаблоні стратегії, однак у методі Шаблони змінюються лише деякі речі (частини алгоритму), а решта речей залишається незмінною. У методі шаблонів інваріантні етапи реалізовані в абстрактному базовому класі, тоді як варіанти варіантів або реалізовані за замовчуванням, або взагалі відсутні. У методі «Шаблон» дизайнер компонентів встановлює необхідні кроки алгоритму та впорядкування кроків, але дозволяє клієнтові компонентів розширити або замінити деяку кількість цих кроків.

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



11

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

Різниця між ними полягає в тому, що хоча схема стратегії дозволяє різним реалізаціям використовувати абсолютно різні способи досягнення бажаного результату, шаблон шаблону методу визначає алгоритм всебічного пошуку (метод "шаблон"), який використовується для досягнення результату - - єдиний вибір, який залишається конкретним реалізаціям (підкласам) - це певні деталі згаданого методу шаблону. Це робиться за допомогою методу шаблону здійснювати виклики до одного або декількох абстрактних методів, які переосмислюються (тобто реалізуються) підкласами, на відміну від шаблонного методу, який сам по собі не абстрактний і не перекритий підкласами .

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


9

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

  1. Він заснований на спадкуванні
  2. Визначає скелет алгоритму, який не можна змінити підкласами. У підкласах можуть бути замінені лише певні операції
  3. Батьківський клас повністю керує алгоритмом і відрізняється лише певними кроками до конкретних класів
  4. Пов'язування проводиться під час компіляції

Структура шаблону_методу :

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

Стратегія:

  1. Він заснований на делегації / складі
  2. Він змінює кишки об'єкта , змінюючи поведінку методу
  3. Він використовується для перемикання між сімейством алгоритмів
  4. Він змінює поведінку об'єкта під час виконання, повністю замінюючи один алгоритм іншим алгоритмом під час виконання
  5. Обв'язування проводиться під час виконання

Структура стратегії :

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

Ознайомтеся зі способом шаблону та статтями стратегії для кращого розуміння.

Схожі повідомлення:

Шаблон дизайну шаблонів у JDK не зміг знайти метод, що визначає набір методів, які потрібно виконати за порядком

Приклад реального світу стратегії


3

Ні, вони не обов'язково споживаються однаково. Шаблон "шаблонного методу" - це спосіб надання "рекомендацій" майбутнім виконавцям. Ви говорите їм: "У всіх об'єктів має бути номер соціального страхування" (це тривіальний приклад, але він ідею відповідає правильно).

Шаблон стратегії дозволяє включати та виключати кілька можливих реалізацій. Він не (як правило) реалізується шляхом успадкування, а натомість, дозволяючи абоненту пройти бажану реалізацію. Прикладом може бути надання можливості доставціCalculator одним із декількох різних способів обчислення податків (реалізація NoSalesTax та можливо реалізація PercentageBasedSalesTax).

Отже, іноді клієнт фактично підкаже об'єкту, яку стратегію використовувати. А саме

myShippingCalculator.CalculateTaxes(myCaliforniaSalesTaxImpl);

Але клієнт ніколи цього не зробив би для об'єкта, який базувався на шаблонній методиці. Насправді клієнт може навіть не знати, що об’єкт заснований на методі шаблонів. Ці абстрактні методи у шаблоні методу шаблонів можуть бути навіть захищені, і тоді клієнт навіть не знає, що вони існують.


3

Я б запропонував вам прочитати цю статтю. Це пояснює відмінності на прикладі реального випадку.

Цитата із статті

" Як можна побачити класи реалізації, також залежать від класу шаблону методу. Ця залежність викликає зміну методу шаблону, якщо потрібно змінити деякі кроки алгоритму. З іншого боку стратегія повністю інкапсулює алгоритм. Це дає реалізацію класи, щоб повністю визначити алгоритм, тому, якщо будь-яка зміна настає, потрібно змінити код для попередньо написаних класів. Це було основною причиною вибору стратегії проектування класів.

Однією з особливостей шаблонного методу є те, що шаблонний метод керує алгоритмом. Що може бути хорошою справою в іншій ситуації, але в моїй проблемі це обмежувало мене розробляти класи. З іншого боку, стратегія не контролює кроки алгоритму, що дозволяє мені додавати абсолютно різні методи перетворення. Тому в моєму випадку стратегія допомагає мені в реалізації.

Одним із недоліків стратегії є те, що занадто багато надмірності коду та менше спільного використання коду. Як очевидно в представленому прикладі цієї статті, я повинен повторювати один і той же код у чотирьох класах знову і знову. Тому важко підтримувати, тому що якщо зміниться впровадження нашої системи, такої як крок 4, загальний для всіх, мені доведеться оновити це у всіх 5 класах. З іншого боку, в шаблонній методиці я можу змінити лише надклас і зміни відображаються в підкласах. Тому шаблонний метод дає дуже низьку кількість надмірності та великий обмін кодом між класами.

Стратегія також дозволяє змінювати алгоритм під час виконання. У шаблонній методиці доведеться повторно ініціалізувати об'єкт. Ця особливість стратегії забезпечує велику кількість гнучкості. З дизайнерської точки зору слід віддавати перевагу композиції, ніж спадкоємству. Тому використання стратегічного шаблону також стало основним вибором для розвитку ".


2

Шаблон шаблону схожий на шаблон стратегії. Ці дві закономірності відрізняються за обсягом та методологією.

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

Інша основна відмінність полягає в тому, що стратегія використовує делегування, тоді як метод шаблону використовує спадкування. У стратегії алгоритм делегований іншому класу xxxStrategy, на який суб'єкт матиме посилання, але за допомогою шаблону ви підкласируєте базовий і переосмислюєте методи внесення змін.

від 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 Spring - це інтерфейс стратегії для вирішення повідомлень. Клієнт використовує певну реалізацію (стратегію) цього інтерфейсу.

І абстрактна реалізація того ж інтерфейсу AbstractMessageSource, який має загальну реалізацію розв’язувальних повідомлень та викриває абстрактний метод resolutionCode (), щоб підкласи могли реалізовувати їх своїми шляхами. AbstractMessageSource - приклад шаблонного методу.

http://docs.spring.io/spring/docs/4.1.7.RELEASE/javadoc-api/org/springframework/context/support/Ab абстрактMessageSource.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.